]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: add ability to register dependencies between northbound nodes
authorIgor Ryzhov <iryzhov@nfware.com>
Tue, 16 Feb 2021 09:49:25 +0000 (12:49 +0300)
committerIgor Ryzhov <iryzhov@nfware.com>
Fri, 26 Feb 2021 11:42:20 +0000 (14:42 +0300)
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
lib/northbound.c
lib/northbound.h

index 895647cfb76cf116ab1ed79b89cb640760558440..0cf9ce4e60563ce4b1a6c95e35a9b9db7f6867db 100644 (file)
@@ -182,6 +182,25 @@ struct nb_node *nb_node_find(const char *xpath)
        return snode->priv;
 }
 
+void nb_node_set_dependency_cbs(const char *dependency_xpath,
+                               const char *dependant_xpath,
+                               struct nb_dependency_callbacks *cbs)
+{
+       struct nb_node *dependency = nb_node_find(dependency_xpath);
+       struct nb_node *dependant = nb_node_find(dependant_xpath);
+
+       if (!dependency || !dependant)
+               return;
+
+       dependency->dep_cbs.get_dependant_xpath = cbs->get_dependant_xpath;
+       dependant->dep_cbs.get_dependency_xpath = cbs->get_dependency_xpath;
+}
+
+bool nb_node_has_dependency(struct nb_node *node)
+{
+       return node->dep_cbs.get_dependency_xpath != NULL;
+}
+
 static int nb_node_validate_cb(const struct nb_node *nb_node,
                               enum nb_operation operation,
                               int callback_implemented, bool optional)
@@ -527,8 +546,9 @@ int nb_candidate_edit(struct nb_config *candidate,
                      const struct yang_data *previous,
                      const struct yang_data *data)
 {
-       struct lyd_node *dnode;
+       struct lyd_node *dnode, *dep_dnode;
        char xpath_edit[XPATH_MAXLEN];
+       char dep_xpath[XPATH_MAXLEN];
 
        /* Use special notation for leaf-lists (RFC 6020, section 9.13.5). */
        if (nb_node->snode->nodetype == LYS_LEAFLIST)
@@ -544,9 +564,33 @@ int nb_candidate_edit(struct nb_config *candidate,
                dnode = lyd_new_path(candidate->dnode, ly_native_ctx,
                                     xpath_edit, (void *)data->value, 0,
                                     LYD_PATH_OPT_UPDATE);
-               if (!dnode && ly_errno) {
-                       flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed",
-                                 __func__);
+               if (dnode) {
+                       /*
+                        * create dependency
+                        *
+                        * dnode returned by the lyd_new_path may be from a
+                        * different schema, so we need to update the nb_node
+                        */
+                       nb_node = dnode->schema->priv;
+                       if (nb_node->dep_cbs.get_dependency_xpath) {
+                               nb_node->dep_cbs.get_dependency_xpath(
+                                       dnode, dep_xpath);
+
+                               ly_errno = 0;
+                               dep_dnode = lyd_new_path(candidate->dnode,
+                                                        ly_native_ctx,
+                                                        dep_xpath, NULL, 0,
+                                                        LYD_PATH_OPT_UPDATE);
+                               if (!dep_dnode && ly_errno) {
+                                       flog_warn(EC_LIB_LIBYANG,
+                                                 "%s: lyd_new_path(%s) failed",
+                                                 __func__, dep_xpath);
+                                       return NB_ERR;
+                               }
+                       }
+               } else if (ly_errno) {
+                       flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed",
+                                 __func__, xpath_edit);
                        return NB_ERR;
                }
                break;
@@ -558,6 +602,14 @@ int nb_candidate_edit(struct nb_config *candidate,
                         * whether to ignore it or not.
                         */
                        return NB_ERR_NOT_FOUND;
+               /* destroy dependant */
+               if (nb_node->dep_cbs.get_dependant_xpath) {
+                       nb_node->dep_cbs.get_dependant_xpath(dnode, dep_xpath);
+
+                       dep_dnode = yang_dnode_get(candidate->dnode, dep_xpath);
+                       if (dep_dnode)
+                               lyd_free(dep_dnode);
+               }
                lyd_free(dnode);
                break;
        case NB_OP_MOVE:
index 7b481273cb94345cdc5eb2c96065a42aa8490a0d..b1ae9ffa00c7c3a927f8d3e0ac74d39525fbc358 100644 (file)
@@ -503,6 +503,11 @@ struct nb_callbacks {
        void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode);
 };
 
+struct nb_dependency_callbacks {
+       void (*get_dependant_xpath)(const struct lyd_node *dnode, char *xpath);
+       void (*get_dependency_xpath)(const struct lyd_node *dnode, char *xpath);
+};
+
 /*
  * Northbound-specific data that is allocated for each schema node of the native
  * YANG modules.
@@ -517,6 +522,8 @@ struct nb_node {
        /* Priority - lower priorities are processed first. */
        uint32_t priority;
 
+       struct nb_dependency_callbacks dep_cbs;
+
        /* Callbacks implemented for this node. */
        struct nb_callbacks cbs;
 
@@ -712,6 +719,12 @@ void nb_nodes_delete(void);
  */
 extern struct nb_node *nb_node_find(const char *xpath);
 
+extern void nb_node_set_dependency_cbs(const char *dependency_xpath,
+                                      const char *dependant_xpath,
+                                      struct nb_dependency_callbacks *cbs);
+
+bool nb_node_has_dependency(struct nb_node *node);
+
 /*
  * Create a new northbound configuration.
  *