Subject: [netmod] Questions about how to assign default values with YANG

From: Italo Busi <[email-masked]>
Date: Wed, 20 Jan 2021 08:57:48 +0000

Hi all,

I have read RFC7950 and RFC8342 but I have still some questions for clarification about how to deal with default values in YANG.

Let's consider a config true leaf for which a YANG default statement has been defined in the YANG module.

If the client does not configure that leaf in the running datastore, the leaf is not present (cannot be read) in the running datastore.

The default value for that leaf is assigned by server in the operational datastore as part of the applied configuration (assuming that other configurations do not override it).

If that leaf exists in the operational datastore, the server shall return the default value if that leaf is read.

Is our understanding correct?

Is it possible for a server not to use that leaf and not to return any value if that leaf is read?

According to this text from RFC8342, it seems that this is possible:

   Requests to retrieve nodes from <operational> always return the value
   in use if the node exists, regardless of any default value specified
   in the YANG module.  If no value is returned for a given node, then
   this implies that the node is not used by the device.

However, according to this text from RFC7950, it seems that this is not possible:

   When the default value is in use, the server MUST operationally
   behave as if the leaf was present in the data tree with the default
   value as its value.
There are case where the default value to assign to a leaf depends on the configuration of other leaves. In this case, the default value cannot be defined using a YANG default statement.

In this case, is it possible in this case to define the default value in the description (maybe referencing some other standard specification)?
Would the behavior of the system be exactly the same as in the cases where the default value is assigned using a YANG default statement?
Would it be possible in this case to define a default value for a leaf defined in a base model which depends on an attribute defined in another model which augments the base model?
In this case, the description of the leaf in the base model cannot be changed in the augmented model. Should the default value for the leaf defined in the base model be described in the description for the leaf defined in the augmenting module?

For example, would this YANG be valid/correct to define a default value 10 for the leaf foo when the leaf bar exist?

module example-base {
  container example {
    leaf foo {
      type uint8;
    }
  }
}

module example-augment {
  import example {
    prefix ex;
  }

  augment "ex:example" {
    leaf bar {
      type empty;
      description
        "When present, the default value for foo is 10.";
    }
  }
}

Thanks for your help

Italo

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 20 Jan 2021 10:47:37 +0100

> Is our understanding correct?

Yes. And you would tag the value with or:origin="or:default", appendix C.1
in RFC 8342 is a good example.
 
>    behave as if the leaf was present in the data tree with the default

I do not see the conflict. Note that RFC 7950 predates the notion of
an operational datastore.

> Would the behavior of the system be exactly the same as in the cases where the default value is assigned using a YANG default statement?

RFC 8342 says:

   o  default: represents configuration using a default value specified
      in the data model, using either values in the "default" statement
      or any values described in the "description" statement.  The
      default origin is only used when the configuration has not been
      provided by any other source.

and

     identity default {
       base origin;
       description
         "Denotes configuration that does not have a configured or
          learned value but has a default value in use.  Covers both
          values defined in a 'default' statement and values defined
          via an explanation in a 'description' statement.";
     }

So it is possible to define the default in a description clause.

>         "When present, the default value for foo is 10.";

Well, this may be meaningful in some cases but it is also risky, if
multiple augementations start to disagree on what should be the
default of some other leaf. Alternatively, you could report the value
foo=10 with the origin "system". For most clients, it likely does not
matter much whether foo=10 is reported with origin=default or
origin=system if the default derivation logic becomes more complex.

For me personally, if there is more complex logic involved in deriving
a value for a leaf (i.e., the existence of other leafs or values of
other leafs matter), then I would rather call it a system provided
value and not a default value.

/js

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

---

From: Italo Busi <[email-masked]>
Date: Wed, 20 Jan 2021 10:51:09 +0000

Juergen,

Thanks for your quick and clear reply.

Thanks also for the suggestion of using system provided values instead of default values.

I have only one doubt and one follow-up question:

> I do not see the conflict. Note that RFC 7950 predates the notion of an
> operational datastore.
>

Does it mean that a server may not use/implement in the operational datastore a leaf for which a YANG default statement has been defined?

What would be the value of defining a YANG default statement for  config false leaf?

Italo

> -----Original Message-----
> From: Juergen Schoenwaelder [mailto:[email-masked]]
> Sent: mercoledì 20 gennaio 2021 10:48
> To: Italo Busi <[email-masked]>
> Cc: [email-masked]' <[email-masked]>
> Subject: Re: [netmod] Questions about how to assign default values with
> YANG
> 
> > I have read RFC7950 and RFC8342 but I have still some questions for
> clarification about how to deal with default values in YANG.
> >
> > If the client does not configure that leaf in the running datastore, the leaf is
> not present (cannot be read) in the running datastore.
> >
> > The default value for that leaf is assigned by server in the operational
> datastore as part of the applied configuration (assuming that other
> configurations do not override it).
> >
> Yes. And you would tag the value with or:origin="or:default", appendix C.1 in
> RFC 8342 is a good example.
> 
> I do not see the conflict. Note that RFC 7950 predates the notion of an
> operational datastore.
> 
> > There are case where the default value to assign to a leaf depends on the
> configuration of other leaves. In this case, the default value cannot be defined
> using a YANG default statement.
> >
> > In this case, is it possible in this case to define the default value in the
> description (maybe referencing some other standard specification)?
> >
> > Would the behavior of the system be exactly the same as in the cases where
> the default value is assigned using a YANG default statement?
> 
> RFC 8342 says:
> 
> > Would it be possible in this case to define a default value for a leaf defined in
> a base model which depends on an attribute defined in another model which
> augments the base model?
> > In this case, the description of the leaf in the base model cannot be changed
> in the augmented model. Should the default value for the leaf defined in the
> base model be described in the description for the leaf defined in the
> augmenting module?
> > For example, would this YANG be valid/correct to define a default value 10
> for the leaf foo when the leaf bar exist?
> >
> > module example-base {
> >   container example {
> >     leaf foo {
> >       type uint8;
> >     }
> >   }
> > }
> >
> > module example-augment {
> >   import example {
> >     prefix ex;
> >   }
> >
> >   augment "ex:example" {
> >     leaf bar {
> >       type empty;
> >       description
> Well, this may be meaningful in some cases but it is also risky, if multiple
> augementations start to disagree on what should be the default of some other
> leaf. Alternatively, you could report the value
> foo=10 with the origin "system". For most clients, it likely does not matter
> much whether foo=10 is reported with origin=default or origin=system if the
> default derivation logic becomes more complex.
> 
> For me personally, if there is more complex logic involved in deriving a value
> for a leaf (i.e., the existence of other leafs or values of other leafs matter), then
> I would rather call it a system provided value and not a default value.
> 
> /js
> 
> --

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 20 Jan 2021 12:44:46 +0100

> Does it mean that a server may not use/implement in the operational datastore a leaf for which a YANG default statement has been defined?

RFC 7950 section 7.6.1 mentions describes situations where a leaf is
conditional, i.e., there is when condition or an if-feature expression
or the leaf is a case node.

> What would be the value of defining a YANG default statement for  config false leaf?

Technically, this can happen because a type has a defined default
value and this type may be used by config false leafs.

An example is the zero-based-counter32 typedef in RFC 6991. However,
this style may be debated since it (mis)uses a default statement to
define an initial value. I am not sure whether the pattern of using
default statements for specifying intial values is a good one.

/js

---

From: Italo Busi <[email-masked]>
Date: Wed, 20 Jan 2021 14:41:39 +0000

Thanks again Juergen,

This was really helpful

I still have one doubt:

> > Does it mean that a server may not use/implement in the operational
> datastore a leaf for which a YANG default statement has been defined?
> >
> 
> conditional, i.e., there is when condition or an if-feature expression or the leaf
> is a case node.
>

What about the case the leaf is not conditional (but still mandatory false since a YANG default statement is defined)?

May the server still decide not to use/implement this leaf in the operational datastore?

For example, in appendix C.1 of RFC8342, auto-negotiation is enabled by default.
What should be the behavior of a system which does not implement auto-negotiation?
Return the value false or no value (in the operational datastore)?

Italo

> Sent: mercoledì 20 gennaio 2021 12:45
> > Does it mean that a server may not use/implement in the operational
> datastore a leaf for which a YANG default statement has been defined?
> >
> 
> conditional, i.e., there is when condition or an if-feature expression or the leaf
> is a case node.
> 
> Technically, this can happen because a type has a defined default value and
> this type may be used by config false leafs.
> 
> An example is the zero-based-counter32 typedef in RFC 6991. However, this
> style may be debated since it (mis)uses a default statement to define an initial
> value. I am not sure whether the pattern of using default statements for
> specifying intial values is a good one.
> 
> /js
> 
> --

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 20 Jan 2021 17:05:17 +0100

> Return the value false or no value (in the operational datastore)?

Here are some of the rules I personally like:

 - <operational> is the ground truth about what a system has and does
 - do not implement leafs that do not apply

Hence, interfaces supporting auto-negotiation have either
auto-negotiation/enabled = true or auto-negotiation/enabled = false in
<operational>. And interfaces not supporting auto-negotiation have
nothing to report about auto-negotiation. Yes, I do not want to see
auto-negotiation/enabled = false on a loopback interface.

My historic Ethernet interface from the last century would also not
report auto-negotiation/enabled in <operational>. You may hit
applications that love to have auto-negotiation/enabled available on
all Ethernet interfaces and then you end in a debate where the
application developers tell you that no information in <operational>
may have many reasons (instrumentation not implemented, access control
rules, whatever and by reporting enabled=false you do them a favor)
but the true answer in such a debate is often that modeling things as
a boolean is simplistic since there are often more than exactly two
states (in this case, enabled, disabled, failed, not-available, ...).
So you settle on blaming the model writer. ;-)

/js