Subject: [netmod] Is current() broken for path expressions defined inside notifications/rpcs?

From: Jernej Tuljak <[email-masked]>
Date: Fri, 14 Mar 2014 15:52:50 +0100

Hi,

RFC6020, Section 9.9.2.:

    o  The context node is the node in the data tree for which the "path"
       statement is defined.

    The accessible tree depends on the context node:

    o  If the context node represents configuration data, the tree is the
       data in the NETCONF datastore where the context node exists.  The
       XPath root node has all top-level configuration data nodes in all
       modules as children.

    o  Otherwise, the tree is all state data on the device, and the
       <running/> datastore.  The XPath root node has all top-level data
       nodes in all modules as children.

RFC6020, Section 3.

    o  data node: A node in the schema tree that can be instantiated in a
       data tree.  One of container, leaf, leaf-list, list, and anyxml.

    o  data tree: The instantiated tree of configuration and state data
       on a device.

A leafref defined within a notification/rpc definition is a not part of 
the data tree, right? It cannot be instantiated as configuration or 
state data, since it represents neither.  So what is current() supposed 
to return in this case?

RFC6020, Section 6.4.1.

    o  The function library is the core function library defined in
       [XPATH  <https://tools.ietf.org/html/rfc6020#ref-XPATH>], and a function "current()" that returns a node set with
       the initial context node.

This function should only be able to return nodes, that are part of the 
accessible tree for an expression, yet in case of notifications and 
rpcs, the text seems to say that the initial context node is not part of 
the accessible tree. Are there two accessible trees?

Section 9.9.2. has an example where current() is used inside a 
notification, which indicates what's supposed to happen, but can it?

    The following notification defines two leafrefs to refer to an
    existing admin-status:

      notification link-failure {
          leaf if-name {
              type leafref {
                  path "/interface/name";
              }
          }
          leaf admin-status {
              type leafref {
                  path
                    "/interface[name = current()/../if-name]"
                  + "/admin-status";
              }
          }
      }

LP, Jernej

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 14 Mar 2014 15:58:43 +0100 (CET)

Hi,

Yes this is broken.  It is on the list of issues to consider for YANG
1.1.

See inline.

Jernej Tuljak <[email-masked]> wrote:
> A leafref defined within a notification/rpc definition is a not part
> of the data tree, right? It cannot be instantiated as configuration or
> state data, since it represents neither.  So what is current()
> supposed to return in this case?

The root node of the state + running tree, which makes it pretty
meaningless.

>       [XPATH <https://tools.ietf.org/html/rfc6020#ref-XPATH>], and a
>       function "current()" that returns a node set with
> This function should only be able to return nodes, that are part of
> the accessible tree for an expression, yet in case of notifications
> and rpcs, the text seems to say that the initial context node is not
> part of the accessible tree. Are there two accessible trees?
> 

This needs to be fixed.

/martin

---

From: Andy Bierman <[email-masked]>
Date: Fri, 14 Mar 2014 08:25:13 -0700

Hi,

> Yes this is broken.  It is on the list of issues to consider for YANG
Same applies for leafref in a typedef-stmt or within a grouping.

See inline.
> The root node of the state + running tree, which makes it pretty

The root, no -- the expression: yes.
The root is just a conceptual node that
has as its child nodes all top-level YANG data nodes.
This part is easy to implement.

The problem is the current() function since the context node is not part
of the same document as the rest of the expression.  This is broken.

Our code does a simple hack that sort of works ;-)
The context node is set to the document root if it is unknown.

> >                    "/interface[name = current()/../if-name]"

Andy

---

From: Jernej Tuljak <[email-masked]>
Date: Mon, 17 Mar 2014 09:50:32 +0100

Dne 14.3.2014 16:25, pis(e Andy Bierman:
> Hi,
>
>
> On Fri, Mar 14, 2014 at 7:58 AM, Martin Bjorklund <[email-masked] 
> <mailto:[email-masked]>> wrote:
>
>     Hi,
>
>     Jernej Tuljak <[email-masked]
>     <mailto:[email-masked]>> wrote:
>     > Hi,
>     >
>     > RFC6020, Section 9.9.2. <http://9.9.2.>:
>     >

Doesn't this just break things further for you? The grammar definition 
for path-arg in section 12. specifies that current function invocation 
*must* be followed by a relative path, which always starts with a 
dot-dot (an abbreviation for parent::node()), which always selects 
nothing in your case. Document root has no parent.

    path-arg            = absolute-path / relative-path

    absolute-path       = 1*("/" (node-identifier *path-predicate))

    relative-path       = 1*(".." "/") descendant-path

    descendant-path     = node-identifier
                          [*path-predicate absolute-path]

    path-predicate      = "[" *WSP path-equality-expr *WSP "]"

    path-equality-expr  = node-identifier *WSP "=" *WSP path-key-expr

    path-key-expr       = current-function-invocation *WSP "/" *WSP
                          rel-path-keyexpr

    rel-path-keyexpr    = 1*(".." *WSP "/" *WSP)
                          *(node-identifier *WSP "/" *WSP)
                          node-identifier

Your hack would have to work so "current()/.." selects the document 
root, right? Seems, well, broken further.. :)

A proper implementation of RFC6020 would probably have to prohibit usage 
of current() for notifications and rpcs, therefore prohibiting usage of 
path predicates. Not so sure about typedefs and groupings though ("the 
node in the data tree for which the "path" statement is defined" seems 
to suggest otherwise; not a problem for used groupings and typedefs 
where the expressions actually matter).

Perhaps temporarily adding the accessible tree of a notification/rpc to 
whatever the text specifies ATM would be a more appropriate solution 
(add a fake notification/rpc sibling to "state + running", where this 
fake subtree is constructed the same way as an accessible tree for 
must/when expressions in the analogous case). I get the feeling that 
this was the original intention so I think I'll try to implement this 
instead of current() returning the document root.

Jernej

---

From: Andy Bierman <[email-masked]>
Date: Mon, 17 Mar 2014 07:26:40 -0700

On Mon, Mar 17, 2014 at 1:50 AM, Jernej Tuljak <[email-masked]>wrote:

>  Dne 14.3.2014 16:25, piše Andy Bierman:
>
> Hi,
>
>
> Doesn't this just break things further for you? The grammar definition for
> path-arg in section 12. specifies that current function invocation *must*
> be followed by a relative path, which always starts with a dot-dot (an
> abbreviation for parent::node()), which always selects nothing in your
> case. Document root has no parent.
>
> Your hack would have to work so "current()/.." selects the document root,
> right? Seems, well, broken further.. :)
>
> path predicates. Not so sure about typedefs and groupings though ("the node
> in the data tree for which the "path" statement is defined" seems to
> suggest otherwise; not a problem for used groupings and typedefs where the
> expressions actually matter).
>
>

The code goes through the XPath 3 at least 3 separate times.
The docroot hack will only generate warnings.  The current() syntax is
checked
completely when there is a context node to check.  (e.g, check the typedef,
check the grouping, check the uses expansion).

> whatever the text specifies ATM would be a more appropriate solution (add a
> fake notification/rpc sibling to "state + running", where this fake subtree
> is constructed the same way as an accessible tree for must/when expressions
> in the analogous case). I get the feeling that this was the original
> intention so I think I'll try to implement this instead of current()
> returning the document root.
>

I don't think mixing documents in the same expression was ever
discussed or intended. It is not clear if increasing the XPath complexity
required for YANG is warranted or not.

Andy