2

For the following

module yy {
  yang-version 1.1;
  namespace "urn:example:yy";
  prefix yyX;


  container x4 {
      leaf x5 {
          type string;
      }
    }

  grouping gx {
          leaf l {
              type leafref {
                  path "../x4/x5";
              }
          }
     }
}

And

module tt {
  yang-version 1.1;
  namespace "urn:example:tt";
  prefix ttX;

  import yy {
    prefix zz;
  }

  container ty {
     uses zz:gx;
  }  
}

yang -f yin tt.yang

.\yy.yang:16: error: yy:x4 in the path for l at tt.yang:11 (at .\yy.yang:14) is not found

  1. module yy does have container x4 , right ?
  2. since leafrefs under grouping are resolved w.r.t the place where they are used, why does it not work if I move the container x4 to tt.yang instead ?
user19937
  • 587
  • 1
  • 7
  • 25

1 Answers1

3

This is a nice example of why defining a non-reusable grouping is a bad idea. That is what your grouping represents. It "references" definitions in the context where it is defined (and not within the grouping itself), not where it is used.

The nodes in a grouping lack context (namespaces, etc.) until used. For example, you cannot tell which node is the parent node of leaf l, until the grouping is used - that is because groupings are not part of the schema tree until used. Upon usage, nodes in the grouping are copied to where the uses appears, thereby replacing it.

So what happens when you do use your grouping and the compiler hits your leafref? Well, it will try to find the referenced node in the context where the grouping is used, that is, the tt module. You used the grouping within the ty container, so the schema tree looks like this:

+--rw container ty
  +--rw leaf l?  leafref

Your expression is ../x4/x5, which in a longer form means parent::*/child::x4/child::x5. The initial context of the expression is the l leaf in the schema tree. So broken into three steps, your expression evaluates to:

+-----------+----------------+----------------+--------------+
|   Step    |    Context     |     Result     | Final result |
+-----------+----------------+----------------+--------------+
| parent::* | leaf l         | container ty   |              |
| child::x4 | container ty   | empty node set |              |
| child::x5 | empty node set | empty node set | <--          |
+-----------+----------------+----------------+--------------+

Yep, there is noting that matches the expression.

If you move the container to the tt module, you get the following schema tree:

+--rw container x4
  +--rw leaf x5? string
+--rw container tt
  +--rw leaf l?  leafref

You should be able to tell by now, that this isn't going to work either. The reason is - the grouping assumes the context in which it will be used, which is bad practice. Since the context does not match the expression, you get broken YANG.

Another important concept is the scope of the path expression. The expression is only able to "see" definitions reachable by the module where the grouping is used, not where it is defined. That is why the two example schema trees above are intentionally different.

predi
  • 5,528
  • 32
  • 60