Subject: [YANG] key ambiguity?

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 04 Dec 2007 09:00:21 -0800

Hi,

is the following fragment legal in YANG?

list lll {
  key id;
  container aaa {
    leaf id { ... }
  }
  container bbb {
    leaf id { ... }
  }
}

If so, then the key is ambiguous. Perhaps the key should contain an
XPath expression?

Cheers, Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

_______________________________________________
YANG mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/yang

---

From: Andy Bierman <[email-masked]>
Date: Tue, 04 Dec 2007 09:27:42 -0800

> If so, then the key is ambiguous. Perhaps the key should contain an

Yes -- this has been discussed and it is what I have implemented.
The construct you defined in illegal in YANG right now, but I
think there might be consensus to change it.

The key "aaa/id bbb/id" would be valid with this change.

> Cheers, Lada

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 04 Dec 2007 09:43:44 -0800

> think there might be consensus to change it.

Why is it illegal, because of the key ambiguity or another reason?

> The key "aaa/id bbb/id" would be valid with this change.

Alternative option would be to indicate inside the leaf that it is a key
for an enclosing list:

leaf id {
  key ../lll;
  ...
}

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Phil Shafer <[email-masked]>
Date: Tue, 04 Dec 2007 12:52:38 -0500

>Why is it illegal, because of the key ambiguity or another reason?

"key id" is illegal, since there is no "id" leaf immediately under
"lll".  Your YANG parser should give you a compiler error.  You'd
need to qualify it as "aaa/id" or "bbb/id" or even "aaa/id bbb/id".

>Alternative option would be to indicate inside the leaf that it is a key

This would mean you'd need to look in multiple places to find
the keys.  Early in YANG, we did something like this, but moved
to the current notation for this reason.

Thanks,
 Phil

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 04 Dec 2007 10:20:14 -0800

> need to qualify it as "aaa/id" or "bbb/id" or even "aaa/id bbb/id".

The production rule for key-arg in Appendix D only allows sequence of
identifiers.

> to the current notation for this reason.

On the other hand it makes life harder to the agent, e.g., when asked to
delete a leaf, it would have to check the ancestry chain whether this
leaf is not among the keys of some list.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Phil Shafer <[email-masked]>
Date: Tue, 04 Dec 2007 13:23:15 -0500

Phil Shafer writes:
>Your YANG parser should give you a compiler error.  You'd

Martin points out that we don't support deep keys in YANG.  We
debated this for a while and ended up dumping them to keep the
rule that keys must appear first in list entries.  Sorry for the
misinformation.

Thanks,
 Phil

---

From: "Randy Presuhn" <[email-masked]>
Date: Tue, 4 Dec 2007 10:35:02 -0800

Hi -

Perhaps it's time to recognize that containers are objects
(forgive the language) and as such deserve instance names
of their own, even if there might be only one with a
particular parent.

Randy

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 04 Dec 2007 10:51:32 -0800

> rule that keys must appear first in list entries.  Sorry for the

OK, then the draft should say that the key consists of identifiers of
*child leafs*, and maybe also explain that if there is no such leaf
(like in my example), it must be created. Anyway, this restriction is
quite problematic - it actually seems to me that lists with structured
items (containers) cannot be constructed at all. In such cases, the key
simply cannot be a child of the list statement.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Tue, 04 Dec 2007 11:18:06 -0800

> simply cannot be a child of the list statement.

I do not agree that the leaf will be created if the identifier in
the key does not exist.  The compiler does not know the
correct data type to use for the key.  The identifier could
be a typo, and a new leaf is not what the DM writer wanted
at all.

I want the ability to have deep keys.
However , there are CLRs to consider.
A nested key cannot be within a choice or another list.
The key components need to be unambiguous and there
must be exactly one instance of each key component.
Therefore only leafs within containers could qualify.

The use case is an important one.
If a DM writer couples 2 leaves together (e.g. address, port)
then this construct cannot be used as the key, and cut-and-paste
will have to be used instead to 'undo' the container.

In NCX, I (at first) allowed the container itself to be listed
as the key  (implying a sequence of leaf key components),
but took this out because if the (external) container definition changed,
this also changed the key definition for the list.

The 'SMI way' of listing each index component, in order,
seems the safest and most clear to readers.

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Tue, 4 Dec 2007 21:31:38 +0100

> Alternative option would be to indicate inside the leaf that it is a key

A reason for not going down this path was that we like to have
reusable groupings where the keys can be defined when you use a
grouping rather than being part of a reusable grouping.

/js

-- 
Juergen Schoenwaelder           Jacobs University Bremen gGmbH
Phone: +49 421 200 3587         Campus Ring 1, 28759 Bremen, Germany
Fax:   +49 421 200 3103         <http://www.jacobs-university.de/>

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 04 Dec 2007 13:44:16 -0800

> be a typo, and a new leaf is not what the DM writer wanted

Oh, I didn't mean that the key would be created automatically but rather
by the model designer since the key is required for lists representing
configuration. Without this requirement, many lists would naturally have
only container items.
 
> I want the ability to have deep keys.

It seems absolutely necessary - the only way I can see for creating
lists other than leaf-lists is like this:

<interfaceList>
  <ifIndex>0</ifIndex>
  <interface>...</interface>
  <ifIndex>1</ifIndex>
  <interface>...</interface>
  ...
</interfaceList>

where the ifIndex element is the key for the following (sibling)
interface item, but this is ugly and error-prone.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Tue, 04 Dec 2007 14:00:10 -0800

> interface item, but this is ugly and error-prone.

Why would you even model the interfaces table this way?

We have been using the following example for a few years
in the NETCONF WG:

  <interfaces>
    <interface>
       <name>eth0</name>
       <ifIndex>1</ifIndex>
       <ifMtu>1500</ifMtu>
   </interface>
 </interfaces>

Since ifIndex is part of the interface data, it is included within
the interface element.

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 04 Dec 2007 14:13:03 -0800

> Why would you even model the interfaces table this way?

Because it is the only way that the draft allows: each item MUST have a
leaf key that is a direct child of the list statement.

> We have been using the following example for a few years

Of course, this is the way to do it but you see - the key is deep here.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Tue, 04 Dec 2007 14:17:23 -0800

> leaf key that is a direct child of the list statement.

See the attached YANG file, which is the start of an interfaces model.
The 'name' and 'ifIndex' leafs are children of the list 'interface',
which is legal in YANG.  (The 'name' is the key, not ifIndex.
Not sure if this is too controversial or not.)

Andy

module interfaces {
    namespace "urn:ietf:params:xml:ns:yang:interfaces";
    prefix "if";

    organization
        "YANG Language Design Team";

    contact
        "Andy Bierman <[email-masked]>";

    description
        "This module contains an interfaces table.";

    revision 2007-12-04 {
        description "Initial revision.";
    }

    import ianaTypes { prefix iana; }

    import iftypes { prefix ift; }

    import smi { prefix smi; }

    leaf ifNumber {
        description
          "The number of network interfaces (regardless of their
           current state) present on this system.";
        type int32;
        config false;
        mandatory true;
    }

    leaf ifTableLastChange {
        description
          "The value of sysUpTime at the time of the last creation or
           deletion of an entry in the ifTable.  If the number of
           entries has been unchanged since the last re-initialization
           of the local network management subsystem, then this object
           contains a zero value.";
        type smi:TimeTicks;
        config false;
        mandatory true;
    }

    container interfaces {

      list interface {
  
        key name;

        unique ifIndex;

        leaf name {
             description "The interface name.";
             type string {
               length "1..max";
           }
        }

        leaf IfIndex {
            description
             "A unique value, greater than zero, for each interface.  It
              is recommended that values are assigned contiguously
              starting from 1.  The value for each interface sub-layer
              must remain constant at least from one re-initialization of
              the entity's network management system to the next re-
              initialization.";
            type itf:InterfaceIndex;
        }

        leaf IfDescr {
            description
             "A textual string containing information about the
              interface.  This string should include the name of the
              manufacturer, the product name and the version of the
              interface hardware/software.";
            type smi:DisplayString {
              length "0..255";
            }
            config false;
        }

        leaf IfType {
            description
             "The type of interface.  Additional values for ifType are
              assigned by the Internet Assigned Numbers Authority (IANA),
              through updating the syntax of the IANAifType textual
              convention.";
            type iana:IANAifType;
            config false;
        }
      
        leaf IfMtu {
            description
             "The size of the largest packet which can be sent/received
              on the interface, specified in octets.  For interfaces that
              are used for transmitting network datagrams, this is the
              size of the largest network datagram that can be sent on the
              interface.";
            type int32;
            config true;
        }

/*
           # IfSpeed                 ifSpeed;
           # IfPhysAddress           ifPhysAddress;
           # IfAdminStatus           ifAdminStatus;
           # IfOperStatus            ifOperStatus;
           # IfLastChange            ifLastChange;
           # IfInOctets              ifInOctets;
           # IfInUcastPkts           ifInUcastPkts;
           # IfInNUcastPkts          ifInNUcastPkts;   # deprecated
           # IfInDiscards            ifInDiscards;
           # IfInErrors              ifInErrors;
           # IfInUnknownProtos       ifInUnknownProtos;
           # IfOutOctets             ifOutOctets;
           # IfOutUcastPkts          ifOutUcastPkts;
           # IfOutNUcastPkts         ifOutNUcastPkts;  # deprecated
           # IfOutDiscards           ifOutDiscards;
           # IfOutErrors             ifOutErrors;
           # IfOutQLen               ifOutQLen;        # deprecated
           # IfSpecific              ifSpecific;       # deprecated
*/

    }
  }
}

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 04 Dec 2007 14:35:03 -0800

> Not sure if this is too controversial or not.)

OK, sorry, it was my misunderstanding. I thought the YANG definition
would be

list interfaces {
  container interface {
    ...
  }
}

What confused me was that the list statement in fact defines content of
an list item.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: "James Balestriere (jbalestr)" <[email-masked]>
Date: Wed, 5 Dec 2007 06:46:37 +0800

I am bit confused by this example 

   <interfaces>
     <interface>
        <name>eth0</name>
        <ifIndex>1</ifIndex>
        <ifMtu>1500</ifMtu>
    </interface>
  </interfaces>

what does eth0 mean ? does it count something different to the ifIndex ?
Also, if I have multiple cards with multiple ethernet ports would I have to
create another counter <ifCard> or something ?

James.

> -----Original Message-----
> From: Andy Bierman [mailto:[email-masked]] 
> Sent: Wednesday, 5 December 2007 9:00 AM
> To: Ladislav Lhotka
> Cc: yang
> Subject: Re: [YANG] key ambiguity?
> 
> Ladislav Lhotka wrote:

---

From: Phil Shafer <[email-masked]>
Date: Tue, 04 Dec 2007 17:56:00 -0500

>Of course, this is the way to do it but you see - the key is deep here.

The leaf which is the key must currently be an immediate child of
the list.  The "deep keys" feature adds the ability to use leafs
as keys which are nested in containers under the list.

    <interfaces>
      <interface>
        <name>et-0/0/0</name>
        <mtu>1400</mtu>
      </interface>
      <interface>
        <name>et-0/0/1</name>
        <mtu>1500</mtu>
      </interface>
      <interface>
        <name>et-0/0/2</name>
        <mtu>1024</mtu>
      </interface>
    </interfaces>

The YANG for this would be:

    container interfaces {
        list interface {
            key name;
            leaf name {
               type junos:interface-name;
            }
            leaf mtu {
               type mtu;
            }
        }
    }

An example of deep keys would be:

    <flow-table>
      <flow>
        <source>
          <address>10.1.2.3</address>
          <port>22</port>
        <source>
        <destination>
          <address>10.1.2.4</address>
          <port>22000</port>
        </destination>
        <packet-count>4321</packet-count>
      </flow>
      <flow>
        <source>
          <address>10.1.2.4</address>
          <port>22</port>
        <source>
        <destination>
          <address>10.1.2.5</address>
          <port>22000</port>
        </destination>
        <packet-count>43210</packet-count>
      </flow>
    </flow-table>

The YANG looks like:

    container flow-table {
        grouping endpoint {
            leaf address {
                type inet:address;
            }
            leaf port {
                type inet:port;
            }
        }
        list flow {
            key "source/address source/port destination/address destination/port";
            container source {
                use endpoint;
            }
            container destination {
                use endpoint;
            }
            leaf packet-count {
                type uint32;
            }
        }
    }

Deep keys would require looking into the "source" and "destination" containers
to see the keys.  The feature pits the benefits of reusing grouping and having
reasonable looking XML against the benefit of simple keys and not having to
buffer the contents of any additional non-key nodes under containers that
hold key.  For example, if I put a new hierarchy of containers under "source"
in addition to the keys that are currently there, the NETCONF implementation
will have to buffer this content until it has all the keys available.

We didn't like this cost, and didn't like the set of rules that would be
required to avoid scenarios that trigger this buffering.  But it's not
an easy trade-off and will likely be revisited.

Thanks,
 Phil

---

From: Andy Bierman <[email-masked]>
Date: Tue, 04 Dec 2007 17:59:35 -0800

> create another counter <ifCard> or something ?

No. You would name your interface Ethernet0/0, etc.

The higher level issue here is whether NETCONF should follow
the IF-MIB letter for letter when we create an interfaces
table for configuration.   Some people say "toss it all
and start over".  I don't know what approach is best.
That would be for a WG to decide.

I prefer to take advantage of the features of NETCONF and XML
to the fullest extent possible, and not be that concerned with the read-only
IF-MIB from SNMP.

Andy

>>> Oh, I didn't mean that the key would be created 
>>>       
>> automatically but rather
>>     
>>> by the model designer since the key is required for lists 
>>>       
>> representing
>>     
>>> configuration. Without this requirement, many lists would 
>>>       
>> naturally have
>>     
>>> only container items.
>>>  
>>>   
>>>

---

From: Jon Saperia <[email-masked]>
Date: Tue, 4 Dec 2007 22:08:10 -0500

> to the fullest extent possible, and not be that concerned with the  

To the extent we have two methods, SNMP and NETCONF, there must be a  
way for management applications to correctly correlate information  
from, to use your example of IF-MIB with interface configuration.  It  
gets even more interesting with DiffServ.  So the issue for me is not  
whether NETCONF should follow letter for letter, but how one would  
effectively correlate the two universes.  I would trade some XML  
advantages for better applications.

>>> From: Andy Bierman [mailto:[email-masked]] Sent: Wednesday,  
>>> 5 December 2007 9:00 AM
>>> To: Ladislav Lhotka
>>> Cc: yang

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 5 Dec 2007 07:57:54 +0100

On Tue, Dec 04, 2007 at 05:59:35PM -0800, Andy Bierman wrote:

> I prefer to take advantage of the features of NETCONF and XML to the
> fullest extent possible, and not be that concerned with the
> read-only IF-MIB from SNMP.

So far, one guiding principle in YANG has been "if in doubt, follow
the CLI approach rather the SNMP approach". This is probably not
written down anywhere in the ID but I strongly believe into it and
think it should actually be written down as a guiding principle.

/js

---

From: Andy Bierman <[email-masked]>
Date: Sun, 09 Dec 2007 08:41:11 -0800

> think it should actually be written down as a guiding principle.

I think there are more factors than CLI that are of concern to
people interested in a standard data modeling language for NETCONF,
as demonstrated in the BoFs and hallways of IETF 70.

The guiding principle is more of "go with what works", and CLI is
what currently works.  But the IETF also cares about security,
interoperability, usability, overlap with other standards, etc.

There are many terms in YANG that may seem purposefully inconsistent.
Some terminology is from SMIv2/sming, some from C, some from XSD,
some new stuff, and lastly, some existing terms that have different
meanings in other languages.  That probably makes it partly familiar
and partly confusing, to everybody.

Andy