Subject: [netmod] inability to

From: Kent Watsen <[email-masked]>
Date: Thu, 23 Oct 2014 00:14:45 +0000

I'm trying to flatten the netconf-server model from:

   +--rw netconf-server
      +--rw listen
         +--rw endpoint* [name]
            +--rw name    string
            +--rw (transport)
               +--:(ssh) {ssh-listen}?
               |  +--rw ssh
               |     +--rw address    inet:ip-address
               |     +--rw port?      inet:port-number
               +--:(tls) {tls-listen}?
                  +--rw tls
                     +--rw address    inet:ip-address
                     +--rw port?      inet:port-number

To:

   +--rw netconf-server
      +--rw listen
         +--rw endpoint* [name]
            +--rw name         string
            +--rw transport    enumeration
            +--rw address      inet:ip-address
            +--rw port?        inet:port-number

The reason I used the first construct was only so that a grouping could be
used under each "transport" choice, which then could "refine" the port's
default value to the transport-specific value:

             uses listen-per-transport-config {
               refine port {
                 default 830;
               }
             }

Or

             uses listen-per-transport-config {
               refine port {
                 default 6513;
               }
             }

I'm trying again now and still can't find a way to do it.   What I want,
is something like:

        leaf port {
          type inet:port-number;
          default {
            830: when "transport == 'ssh'";
            6513: when "transport == 'tls'";

          }
        }

I did try some wild options, for instance:

      grouping port-grouping {
        leaf port {
          type inet:port-number;
        }
      }

<snip/>
        uses port-grouping {
          when "transport == 'ssh'";
          refine port {
            default 830;
          }
        }
        uses port-grouping {
          when "transport == 'tls'";
          refine port {
            default 6513;
          }
        }

Which failed: 

ietf-netconf-server.yang:178: error: there is already a child node to
"endpoint" at ../ietf-netconf-server.yang:145 with the name "port" defined
at ../ietf-netconf-server.yang:172 (at ../ietf-netconf-server.yang:130)

Any ideas?

Thanks,
Kent

---

From: Xiao SHI <[email-masked]>
Date: Wed, 22 Oct 2014 21:10:59 -0400

Hi Kent,

I ran into similar issues before trying to use YANG. Essentially the caveat
is that the yang validator doesn't check that the when statements are
logically disjoint (if there was one, it should be in semantic check stage
anyway). e.g.
uses groupingA {
  when "condition1";
  leaf node1 {...}
}

uses groupingA {
  when "condition2";
  leaf node1 {...}
}

By doing this, you are essentially creating two nodes of the same name
instead of branching the condition. Similar situations happen when you try
to augment a node with leafs that have the same name but different
structure under different conditions. One possible solution is to use
choice/case on a higher level (which was what you started with).

Using augment and choice, you might be able to flatten it out to this
extent:
   +--rw netconf-server
      +--rw listen
         +--rw endpoint* [name]
            +--rw name    string
            +--rw address    inet:ip-address
            +--rw (transport)
               +--:(ssh) {ssh-listen}?
               |  +--rw ssh
               |     +--rw port?      inet:port-number
               +--:(tls) {tls-listen}?
                  +--rw tls
                     +--rw port?      inet:port-number
But that's not much of an improvement either.

Since the only conditioning substatement of refine is the must statement
(and mandatory statement which is not very helpful here), uses doesn't have
choice as a substatement, I think this flattening might be difficult to
accomplish.

Another foreseeable solution with future extensions is to allow when
statements to take on enum values. But that's complicating the issues at
hand.

Best,
Xiao

On Wed, Oct 22, 2014 at 8:14 PM, Kent Watsen <[email-masked]> wrote:

> _______________________________________________
> netmod mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/netmod
>

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 23 Oct 2014 09:00:01 +0200

Kent,

please take a look at the discussion in this I-D:

http://www.ietf.org/id/draft-schoenw-netmod-yang-pattern-00.txt

I believe having a choice is a good thing and it is a feature to
keep transport specific leafs separate.

/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: Martin Bjorklund <[email-masked]>
Date: Thu, 23 Oct 2014 09:13:09 +0200 (CEST)

>             +--rw port?        inet:port-number

I don't think this is a good idea.  Transports are different and may
have very different configuration parameters; even if they don't have
that currently we want to design for future extensibility, both in
what we configure per protocol and for future protocols.

(This pattern is described in draft-schoenw-netmod-yang-pattern-00; we
should also discuss your suggested design there).

>             6513: when "transport == 'tls'";

Not possible.  defaults in YANG are static.  If you want something
else you have to describe it in text.

(This one does come up every now and then.  Variants include "default
ref" where the default value is configured in some other static leaf,
e.g. "if the timeout isn't set for a particular instance, use the
globally defined value:  "default-ref ../../global-params/timeout", or
even dynamic default refs such as "if the timeout isn't set for a
particualr instance, use the value from the configured profile")

/martin

---

From: Kent Watsen <[email-masked]>
Date: Thu, 23 Oct 2014 15:36:36 +0000

>keep transport specific leafs separate.

I got the original design from that draft, of course.  Flattening it as
described earlier still preserves the outlined goals (leafrefs, future VRF
augmentation, etc.).  That said, I'm overlooking that not all transports
are IP based, and thus you're right about needing to isolate them, even if
both case statements are currently identical, they may not always be -
e.g., configuring the host-keys / certificates the server should
advertise...

Maybe update your draft to highlight this goal more clearly?

In the meanwhile, I'll go back to the original model.

Thanks,
Kent

---

From: Andy Bierman <[email-masked]>
Date: Thu, 23 Oct 2014 08:54:46 -0700

> what we configure per protocol and for future protocols.
+1
I like the old design better

> else you have to describe it in text.

Maybe something for YANG 2.0?

        uses listen-per-transport-config {
            if "transport = 'ssh'" {
                 refine port {
                     default 830;
                 }
             }
             elif "transport = 'tls'" {
                 refine port {
                     default 830;
                 }
             }
             // else no port default
         }

> particualr instance, use the value from the configured profile")

Andy

---

From: Andy Bierman <[email-masked]>
Date: Thu, 23 Oct 2014 08:56:13 -0700

>              elif "transport = 'tls'" {

oops   -- supposed to be 6513 here!