forked from Mirror/frr
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:
parent
565f463e30
commit
27802d3fee
144
lib/yang.c
144
lib/yang.c
|
@ -749,3 +749,147 @@ void yang_terminate(void)
|
||||||
|
|
||||||
ly_ctx_destroy(ly_native_ctx, NULL);
|
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;
|
||||||
|
}
|
||||||
|
|
53
lib/yang.h
53
lib/yang.h
|
@ -34,7 +34,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Maximum XPath length. */
|
/* Maximum XPath length. */
|
||||||
#define XPATH_MAXLEN 512
|
#define XPATH_MAXLEN 1024
|
||||||
|
|
||||||
/* Maximum list key length. */
|
/* Maximum list key length. */
|
||||||
#define LIST_MAXKEYS 8
|
#define LIST_MAXKEYS 8
|
||||||
|
@ -551,6 +551,57 @@ extern void yang_init(bool embedded_modules);
|
||||||
*/
|
*/
|
||||||
extern void yang_terminate(void);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue