* [Identityref inside augment statement](https://github.com/clicon/clixon/issues/77)

* Yang-stmt enhanced with "shortcut" to original module
This commit is contained in:
Olof hagsand 2019-03-05 22:41:41 +01:00
parent efe44d60e8
commit 01c8b0b836
7 changed files with 103 additions and 14 deletions

View file

@ -34,6 +34,8 @@
* Added libgen.h for baseline() * Added libgen.h for baseline()
### Corrected Bugs ### Corrected Bugs
* [Identityref inside augment statement](https://github.com/clicon/clixon/issues/77)
* Yang-stmt enhanced with "shortcut" to original module
* Yang augment created multiple augmented children (no side-effect) * Yang augment created multiple augmented children (no side-effect)
* XML prefixed attribute names were not copied into the datastore * XML prefixed attribute names were not copied into the datastore
* [yang type range statement does not support multiple values](https://github.com/clicon/clixon/issues/59) * [yang type range statement does not support multiple values](https://github.com/clicon/clixon/issues/59)

View file

@ -112,12 +112,11 @@ However, the following YANG syntax modules are not implemented:
- min/max-elements - min/max-elements
- unique - unique
- action - action
- refine
Restrictions on Yang types are as follows: Restrictions on Yang types are as follows:
- The range statement for built-in integers does not support multiple values (RFC7950 9.2.4)
- The length statement for built-in strings does not support multiple values (RFC7950 9.4.4)
- Submodules cannot re-use a prefix in an import statement that is already used for another imported module in the module that the submodule belongs to. (see https://github.com/clicon/clixon/issues/60) - Submodules cannot re-use a prefix in an import statement that is already used for another imported module in the module that the submodule belongs to. (see https://github.com/clicon/clixon/issues/60)
- default values on leaf-lists are not supported (RFC7950 7.7.2) - Default values on leaf-lists are not supported (RFC7950 7.7.2)
## XML ## XML

View file

@ -198,6 +198,10 @@ struct yang_stmt{
char *ys_argument; /* String / argument depending on keyword */ char *ys_argument; /* String / argument depending on keyword */
int ys_flags; /* Flags according to YANG_FLAG_* above */ int ys_flags; /* Flags according to YANG_FLAG_* above */
/*--------------here common for all -------*/ /*--------------here common for all -------*/
yang_stmt *ys_module; /* Shortcut to "my" module. Augmented
nodes can belong to other
modules than the ancestor module */
char *ys_extra; /* For unknown */ char *ys_extra; /* For unknown */
cg_var *ys_cv; /* cligen variable. See ys_populate() cg_var *ys_cv; /* cligen variable. See ys_populate()
Following stmts have cv:s: Following stmts have cv:s:

View file

@ -316,6 +316,7 @@ validate_leafref(cxobj *xt,
* @retval 0 Validation failed * @retval 0 Validation failed
* @retval -1 Error * @retval -1 Error
* @see ys_populate_identity where the derived types are set * @see ys_populate_identity where the derived types are set
* @see yang_augment_node
* @see RFC7950 Sec 9.10.2: * @see RFC7950 Sec 9.10.2:
*/ */
static int static int

View file

@ -773,6 +773,7 @@ ys_module_by_xml(yang_spec *ysp,
* @param[in] ys Any yang statement in a yang tree * @param[in] ys Any yang statement in a yang tree
* @retval ymod The top module or sub-module * @retval ymod The top module or sub-module
* @see ys_spec * @see ys_spec
* @note For an augmented node, the original module is returned
*/ */
yang_stmt * yang_stmt *
ys_module(yang_stmt *ys) ys_module(yang_stmt *ys)
@ -786,6 +787,10 @@ ys_module(yang_stmt *ys)
while (ys != NULL && while (ys != NULL &&
ys->ys_keyword != Y_MODULE && ys->ys_keyword != Y_MODULE &&
ys->ys_keyword != Y_SUBMODULE){ ys->ys_keyword != Y_SUBMODULE){
if (ys->ys_module){ /* shortcut due to augment */
ys = ys->ys_module;
break;
}
yn = ys->ys_parent; yn = ys->ys_parent;
/* Some extra stuff to ensure ys is a stmt */ /* Some extra stuff to ensure ys is a stmt */
if (yn && yn->yn_keyword == Y_SPEC) if (yn && yn->yn_keyword == Y_SPEC)
@ -800,6 +805,7 @@ ys_module(yang_stmt *ys)
* @param[in] ys Any yang statement in a yang tree * @param[in] ys Any yang statement in a yang tree
* @retval yspec The top yang specification * @retval yspec The top yang specification
* @see ys_module * @see ys_module
* @see ys_yang_augment_node where shortcut is set
*/ */
yang_spec * yang_spec *
ys_spec(yang_stmt *ys) ys_spec(yang_stmt *ys)
@ -1640,7 +1646,12 @@ yang_augment_node(yang_stmt *ys,
yang_stmt *ytarget = NULL; yang_stmt *ytarget = NULL;
yang_stmt *yc; yang_stmt *yc;
int i; int i;
yang_stmt *ymod;
if ((ymod = ys_module(ys)) == NULL){
clicon_err(OE_YANG, 0, "My yang module not found");
goto done;
}
schema_nodeid = ys->ys_argument; schema_nodeid = ys->ys_argument;
clicon_debug(2, "%s %s", __FUNCTION__, schema_nodeid); clicon_debug(2, "%s %s", __FUNCTION__, schema_nodeid);
/* Find the target */ /* Find the target */
@ -1654,7 +1665,7 @@ yang_augment_node(yang_stmt *ys,
for (i=0; i<ys->ys_len; i++){ for (i=0; i<ys->ys_len; i++){
if ((yc = ys_dup(ys->ys_stmt[i])) == NULL) if ((yc = ys_dup(ys->ys_stmt[i])) == NULL)
goto done; goto done;
/* XXX: use prefix of origin */ yc->ys_module = ymod;
if (yn_insert((yang_node*)ytarget, yc) < 0) if (yn_insert((yang_node*)ytarget, yc) < 0)
goto done; goto done;
} }

View file

@ -772,7 +772,7 @@ ys_typedef_up(yang_stmt *ys)
identityref's base identity. identityref's base identity.
1. (base) identity must exist (be found). This is a sanity check 1. (base) identity must exist (be found). This is a sanity check
of the specification and also necessary for identity statements. of the specification and also necessary for identity statements.
(This is what is dine here) (This is what is done here)
2. Check if a given node has value derived from base identity. This is 2. Check if a given node has value derived from base identity. This is
a run-time check necessary when validating eg netconf. a run-time check necessary when validating eg netconf.
(This is validation) (This is validation)

View file

@ -6,7 +6,6 @@
# both defined in the basic ietf-interfaces module (type) as well as the main # both defined in the basic ietf-interfaces module (type) as well as the main
# module through the augmented module () # module through the augmented module ()
# The ietf-interfaces is very restricted (not original). # The ietf-interfaces is very restricted (not original).
# Work-in-progress
# Magic line must be first in script (see README.md) # Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
@ -36,6 +35,8 @@ cat <<EOF > $cfg
EOF EOF
# Stub ietf-interfaces for test # Stub ietf-interfaces for test
# This is the target module (where the augment is applied to)
# The grouping is from rfc7950 Sec 7.12 with simplified types
cat <<EOF > $fyang2 cat <<EOF > $fyang2
module ietf-interfaces { module ietf-interfaces {
yang-version 1.1; yang-version 1.1;
@ -47,9 +48,6 @@ module ietf-interfaces {
"Base identity from which specific interface types are "Base identity from which specific interface types are
derived."; derived.";
} }
identity eth {
base interface-type;
}
identity fddi { identity fddi {
base interface-type; base interface-type;
} }
@ -68,11 +66,21 @@ module ietf-interfaces {
} }
} }
} }
grouping endpoint {
description "A reusable endpoint group.";
leaf mip {
type string;
}
leaf mport {
type uint16;
}
}
} }
EOF EOF
# From rfc7950 sec 7.17 # From rfc7950 sec 7.17
# Note "when" is not present # Note "when" is not present
# This is the main module where the augment exists
cat <<EOF > $fyang cat <<EOF > $fyang
module example-augment { module example-augment {
yang-version 1.1; yang-version 1.1;
@ -85,12 +93,47 @@ module example-augment {
identity some-new-iftype { identity some-new-iftype {
base if:interface-type; base if:interface-type;
} }
identity my-type {
description "an identity based in the main module";
}
identity you {
base my-type;
}
grouping mypoint {
description "A reusable endpoint group.";
leaf ip {
type string;
}
leaf port {
type uint16;
}
}
augment "/if:interfaces/if:interface" { augment "/if:interfaces/if:interface" {
/* when 'derived-from-or-self(if:type, "mymod:some-new-iftype")'; */ /* when 'derived-from-or-self(if:type, "mymod:some-new-iftype")'; */
leaf mandatory-leaf { leaf mandatory-leaf {
mandatory true; mandatory true;
type string; type string;
} }
leaf me {
type identityref {
base mymod:my-type;
}
}
leaf other {
type identityref {
base if:interface-type;
}
}
uses if:endpoint {
refine port {
default 80;
}
}
uses mypoint {
refine mport {
default 8080;
}
}
} }
} }
EOF EOF
@ -113,14 +156,45 @@ fi
# mandatory-leaf See RFC7950 Sec 7.17 # mandatory-leaf See RFC7950 Sec 7.17
# Error1: the xml should have xmlns for "mymod" # Error1: the xml should have xmlns for "mymod"
# XMLNS_YANG_ONLY must be undeffed # XMLNS_YANG_ONLY must be undeffed
new "netconf set new if my w augmented type" new "netconf set interface with augmented type and mandatory leaf"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"><interface xmlns:mymod="urn:example:augment"><name>my</name><type>mymod:some-new-iftype</type><mymod:mandatory-leaf>true</mymod:mandatory-leaf></interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface xmlns:mymod="urn:example:augment">
<name>e1</name>
<type>mymod:some-new-iftype</type>
<mymod:mandatory-leaf>true</mymod:mandatory-leaf>
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate ok"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "netconf set identity defined in other"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface xmlns:mymod="urn:example:augment">
<name>e2</name>
<type>fddi</type>
<mymod:mandatory-leaf>true</mymod:mandatory-leaf>
<other>if:fddi</other>
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate ok"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "netconf set identity defined in main"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface xmlns:mymod="urn:example:augment">
<name>e3</name>
<type>fddi</type>
<mymod:mandatory-leaf>true</mymod:mandatory-leaf>
<me>mymod:you</me>
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate ok" new "netconf validate ok"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
exit
if [ $BE -eq 0 ]; then if [ $BE -eq 0 ]; then
exit # BE exit # BE
fi fi
@ -135,6 +209,4 @@ fi
stop_backend -f $cfg stop_backend -f $cfg
sudo pkill -u root -f clixon_backend sudo pkill -u root -f clixon_backend
rm -rf $dir rm -rf $dir