lib : Yang wrappers

1. To get the parent node
2. To auto delete the parent when last node in list gets deleted

Signed-off-by: VishalDhingra <vdhingra@vmware.com>
This commit is contained in:
vdhingra 2020-04-24 05:36:14 -07:00
parent 565f463e30
commit 27802d3fee
2 changed files with 196 additions and 1 deletions

View file

@ -749,3 +749,147 @@ void yang_terminate(void)
ly_ctx_destroy(ly_native_ctx, NULL);
}
const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode,
const char *name)
{
const struct lyd_node *orig_dnode = dnode;
while (orig_dnode) {
switch (orig_dnode->schema->nodetype) {
case LYS_LIST:
case LYS_CONTAINER:
if (!strcmp(orig_dnode->schema->name, name))
return orig_dnode;
break;
default:
break;
}
orig_dnode = orig_dnode->parent;
}
return NULL;
}
/* API to check if the given node is last node in the list */
static bool yang_is_last_list_dnode(const struct lyd_node *dnode)
{
return (((dnode->next == NULL)
|| (dnode->next
&& (strcmp(dnode->next->schema->name, dnode->schema->name)
!= 0)))
&& dnode->prev
&& ((dnode->prev == dnode)
|| (strcmp(dnode->prev->schema->name, dnode->schema->name)
!= 0)));
}
/* API to check if the given node is last node in the data tree level */
static bool yang_is_last_level_dnode(const struct lyd_node *dnode)
{
const struct lyd_node *parent;
const struct lys_node_list *snode;
const struct lyd_node *key_leaf;
uint8_t keys_size;
switch (dnode->schema->nodetype) {
case LYS_LIST:
assert(dnode->parent);
parent = dnode->parent;
snode = (struct lys_node_list *)parent->schema;
key_leaf = dnode->prev;
for (keys_size = 1; keys_size < snode->keys_size; keys_size++)
key_leaf = key_leaf->prev;
if (key_leaf->prev == dnode)
return true;
break;
case LYS_CONTAINER:
return true;
default:
break;
}
return false;
}
const struct lyd_node *
yang_get_subtree_with_no_sibling(const struct lyd_node *dnode)
{
bool parent = true;
const struct lyd_node *node;
const struct lys_node_container *snode;
node = dnode;
if (node->schema->nodetype != LYS_LIST)
return node;
while (parent) {
switch (node->schema->nodetype) {
case LYS_CONTAINER:
snode = (struct lys_node_container *)node->schema;
if ((!snode->presence)
&& yang_is_last_level_dnode(node)) {
if (node->parent
&& (node->parent->schema->module
== dnode->schema->module))
node = node->parent;
else
parent = false;
} else
parent = false;
break;
case LYS_LIST:
if (yang_is_last_list_dnode(node)
&& yang_is_last_level_dnode(node)) {
if (node->parent
&& (node->parent->schema->module
== dnode->schema->module))
node = node->parent;
else
parent = false;
} else
parent = false;
break;
default:
parent = false;
break;
}
}
return node;
}
uint32_t yang_get_list_pos(const struct lyd_node *node)
{
return lyd_list_pos(node);
}
uint32_t yang_get_list_elements_count(const struct lyd_node *node)
{
unsigned int count;
struct lys_node *schema;
if (!node
|| ((node->schema->nodetype != LYS_LIST)
&& (node->schema->nodetype != LYS_LEAFLIST))) {
return 0;
}
schema = node->schema;
count = 0;
do {
if (node->schema == schema)
++count;
node = node->next;
} while (node);
return count;
}
const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode)
{
if (dnode)
return dnode->child;
return NULL;
}

View file

@ -34,7 +34,7 @@ extern "C" {
#endif
/* Maximum XPath length. */
#define XPATH_MAXLEN 512
#define XPATH_MAXLEN 1024
/* Maximum list key length. */
#define LIST_MAXKEYS 8
@ -551,6 +551,57 @@ extern void yang_init(bool embedded_modules);
*/
extern void yang_terminate(void);
/*
* API to return the parent dnode having a given schema-node name
* Use case: One has to access the parent dnode's private pointer
* for a given child node.
* For that there is a need to find parent dnode first.
*
* dnode The starting node to work on
*
* name The name of container/list schema-node
*
* Returns The dnode matched with the given name
*/
extern const struct lyd_node *
yang_dnode_get_parent(const struct lyd_node *dnode, const char *name);
/*
* In some cases there is a need to auto delete the parent nodes
* if the given node is last in the list.
* It tries to delete all the parents in a given tree in a given module.
* The use case is with static routes and route maps
* example : ip route 1.1.1.1/32 ens33
* ip route 1.1.1.1/32 ens34
* After this no ip route 1.1.1.1/32 ens34 came, now staticd
* has to find out upto which level it has to delete the dnodes.
* For this case it has to send delete nexthop
* After this no ip route 1.1.1.1/32 ens33 came, now staticd has to
* clear nexthop, path and route nodes.
* The same scheme is required for routemaps also
* dnode The starting node to work on
*
* Returns The final parent node selected for deletion
*/
extern const struct lyd_node *
yang_get_subtree_with_no_sibling(const struct lyd_node *dnode);
/* To get the relative position of a node in list */
extern uint32_t yang_get_list_pos(const struct lyd_node *node);
/* To get the number of elements in a list
*
* dnode : The head of list
* Returns : The number of dnodes present in the list
*/
extern uint32_t yang_get_list_elements_count(const struct lyd_node *node);
/* To get the immediate child of a dnode */
const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode);
#ifdef __cplusplus
}
#endif