Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions lib/src/clixon_validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,25 @@ leafref_opt_cache_new(yang_stmt *ys,
return 0;
}

/*! Count children of xp with yang spec ys
*
* @param[in] xp XML parent
* @param[in] ys Yang spec of children to count
* @retval n Number of children
*/
static size_t
leafref_opt_count(cxobj *xp,
yang_stmt *ys)
{
cxobj *x = NULL;
size_t n = 0;

while ((x = xml_child_each(xp, x, CX_ELMNT)) != NULL)
if (xml_spec(x) == ys)
n++;
return n;
}

/*! Detect if binary search can be used
*
* If xlen is very large, this takes time
Expand All @@ -294,6 +313,7 @@ leafref_opt_cache_new(yang_stmt *ys,
* IF yang of all elements is same YANG
* AND that yang is LEAF-LIST AND is ordered-by system
* OR that yang's parent is LIST AND is ordered-by system
* AND xvec contains all such siblings, ie not filtered by xpath predicates
* THEN use binary search
* @param[in] xvec Vector of matching XML values
* @param[in] xlen Length of xvec
Expand Down Expand Up @@ -369,6 +389,15 @@ leafref_opt_search_detect(cxobj **xvec,
}
}
if (i == xlen && x0 != NULL && xml_parent(x0) && xml_spec(x0)){
/* Binary search covers all siblings, but xvec may be a subset filtered by
* xpath predicates, eg ../iface[enabled='true']/name
*/
if (is_list){
if (xpp == NULL || leafref_opt_count(xpp, y0p) != xlen)
return 0;
}
else if (leafref_opt_count(x0p, y0) != xlen)
return 0;
*search = 1;
*x0pp = x0;
}
Expand Down
31 changes: 30 additions & 1 deletion test/test_leafref.sh
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,18 @@ module example{
leaf template{
type leafref{
path "/sender/name";
require-instance true;
require-instance true;
}
}
leaf enabled{
type boolean;
}
/* leafref filtered by predicate: binary search must not match
* entries excluded by the predicate */
leaf active-template{
type leafref{
path "/sender[enabled='true']/name";
require-instance true;
}
}
}
Expand Down Expand Up @@ -279,6 +290,24 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS>
new "issue 669: discard-changes"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

# Leafref path with predicate on the list: xvec is a subset of the list entries.
# LEAFREF_OPTIMIZE binary search must not be used, it searches all entries and
# would accept a reference to an entry excluded by the predicate.
new "leafref predicate: add senders s1,s3 enabled, s2 disabled, s4 refers to disabled s2"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><sender xmlns=\"urn:example:clixon\"><name>s1</name><enabled>true</enabled></sender><sender xmlns=\"urn:example:clixon\"><name>s2</name><enabled>false</enabled></sender><sender xmlns=\"urn:example:clixon\"><name>s3</name><enabled>true</enabled></sender><sender xmlns=\"urn:example:clixon\"><name>s4</name><active-template>s2</active-template></sender></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "leafref predicate: validate expect failure (s2 is disabled)"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "<rpc-error>" ""

new "leafref predicate: set s4 to refer to enabled s3"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><sender xmlns=\"urn:example:clixon\"><name>s4</name><active-template>s3</active-template></sender></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "leafref predicate: validate expect OK (s3 is enabled)"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "leafref predicate: discard-changes"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

# Leafref to non-key leaf in a list: LEAFREF_OPTIMIZE binary search must not
# be used when the target leaf is not the list key. With two routers present
# (key "vrf-id"), the target leaf "area-tag" is a non-key unique leaf.
Expand Down
Loading