]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib : Yang wrappers
authorvdhingra <vdhingra@vmware.com>
Fri, 24 Apr 2020 12:36:14 +0000 (05:36 -0700)
committervdhingra <vdhingra@vmware.com>
Thu, 16 Jul 2020 15:33:00 +0000 (08:33 -0700)
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>
lib/yang.c
lib/yang.h

index 0714ddf7bbb501846b6fd75d517e8d3a4f39eaf9..db99c0339e27bacd85330978f4a849e0c0283e8e 100644 (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;
+}
index 85ef0d758cd2d2746eb51a3f9da350a92f6945c2..d526d2f5d6a12c8f7c3db2957739bb1581fdd362 100644 (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