]> 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>
Mon, 22 Feb 2021 15:53:24 +0000 (18:53 +0300)
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
lib/northbound.c
lib/northbound.h

index ecfa2c9d11c0bd66f294b0dae3d7a26ca1d51dc4..224951b22bff2e5871b44358f44ed63045c801e7 100644 (file)
@@ -185,6 +185,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)
@@ -532,8 +551,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)
@@ -549,9 +569,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;
@@ -563,6 +607,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 8dd6b4c33751f5944f1f3bd6d2b6aa4e1512e0c4..3e1342f985b50bbf95612814b9339778bda21de0 100644 (file)
@@ -509,6 +509,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.
@@ -523,6 +528,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;
 
@@ -722,6 +729,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.
  *