]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/yang.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / lib / yang.c
index bb5d38e2e664197295306efed1c7c0161f7fc4ef..71b41c35d8225a660650a573549b1c93617c12a2 100644 (file)
@@ -32,6 +32,52 @@ DEFINE_MTYPE(LIB, YANG_DATA, "YANG data structure")
 /* libyang container. */
 struct ly_ctx *ly_native_ctx;
 
+static struct yang_module_embed *embeds, **embedupd = &embeds;
+
+void yang_module_embed(struct yang_module_embed *embed)
+{
+       embed->next = NULL;
+       *embedupd = embed;
+       embedupd = &embed->next;
+}
+
+static const char *yang_module_imp_clb(const char *mod_name,
+                                      const char *mod_rev,
+                                      const char *submod_name,
+                                      const char *submod_rev,
+                                      void *user_data,
+                                      LYS_INFORMAT *format,
+                                      void (**free_module_data)
+                                               (void *, void*))
+{
+       struct yang_module_embed *e;
+
+       if (submod_name || submod_rev)
+               return NULL;
+
+       for (e = embeds; e; e = e->next) {
+               if (strcmp(e->mod_name, mod_name))
+                       continue;
+               if (mod_rev && strcmp(e->mod_rev, mod_rev))
+                       continue;
+
+               *format = e->format;
+               return e->data;
+       }
+
+       flog_warn(EC_LIB_YANG_MODULE_LOAD,
+                 "YANG model \"%s@%s\" not embedded, trying external file",
+                 mod_name, mod_rev ? mod_rev : "*");
+       return NULL;
+}
+
+static const char *const frr_native_modules[] = {
+       "frr-interface",
+       "frr-ripd",
+       "frr-ripngd",
+       "frr-isisd",
+};
+
 /* Generate the yang_modules tree. */
 static inline int yang_module_compare(const struct yang_module *a,
                                      const struct yang_module *b)
@@ -69,6 +115,12 @@ struct yang_module *yang_module_load(const char *module_name)
        return module;
 }
 
+void yang_module_load_all(void)
+{
+       for (size_t i = 0; i < array_size(frr_native_modules); i++)
+               yang_module_load(frr_native_modules[i]);
+}
+
 struct yang_module *yang_module_find(const char *module_name)
 {
        struct yang_module s;
@@ -77,23 +129,18 @@ struct yang_module *yang_module_find(const char *module_name)
        return RB_FIND(yang_modules, &yang_modules, &s);
 }
 
-/*
- * Helper function for yang_module_snodes_iterate() and
- * yang_all_snodes_iterate(). This is a recursive function.
- */
-static void yang_snodes_iterate(const struct lys_node *snode,
-                               void (*func)(const struct lys_node *, void *,
-                                            void *),
-                               uint16_t flags, void *arg1, void *arg2)
+int yang_snodes_iterate_subtree(const struct lys_node *snode,
+                               yang_iterate_cb cb, uint16_t flags, void *arg)
 {
        struct lys_node *child;
+       int ret = YANG_ITER_CONTINUE;
 
        if (CHECK_FLAG(flags, YANG_ITER_FILTER_IMPLICIT)) {
                switch (snode->nodetype) {
                case LYS_CASE:
                case LYS_INPUT:
                case LYS_OUTPUT:
-                       if (snode->flags & LYS_IMPLICIT)
+                       if (CHECK_FLAG(snode->flags, LYS_IMPLICIT))
                                goto next;
                        break;
                default:
@@ -123,7 +170,7 @@ static void yang_snodes_iterate(const struct lys_node *snode,
                break;
        case LYS_GROUPING:
                /* Return since we're not interested in the grouping subtree. */
-               return;
+               return YANG_ITER_CONTINUE;
        case LYS_USES:
        case LYS_AUGMENT:
                /* Always ignore nodes of these types. */
@@ -137,50 +184,66 @@ static void yang_snodes_iterate(const struct lys_node *snode,
                break;
        }
 
-       (*func)(snode, arg1, arg2);
+       ret = (*cb)(snode, arg);
+       if (ret == YANG_ITER_STOP)
+               return ret;
 
 next:
        /*
         * YANG leafs and leaf-lists can't have child nodes, and trying to
         * access snode->child is undefined behavior.
         */
-       if (snode->nodetype & (LYS_LEAF | LYS_LEAFLIST))
-               return;
+       if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST))
+               return YANG_ITER_CONTINUE;
 
        LY_TREE_FOR (snode->child, child) {
-               if (child->parent != snode)
+               if (!CHECK_FLAG(flags, YANG_ITER_ALLOW_AUGMENTATIONS)
+                   && child->parent != snode)
                        continue;
-               yang_snodes_iterate(child, func, flags, arg1, arg2);
+
+               ret = yang_snodes_iterate_subtree(child, cb, flags, arg);
+               if (ret == YANG_ITER_STOP)
+                       return ret;
        }
+
+       return ret;
 }
 
-void yang_module_snodes_iterate(const struct lys_module *module,
-                               void (*func)(const struct lys_node *, void *,
-                                            void *),
-                               uint16_t flags, void *arg1, void *arg2)
+int yang_snodes_iterate_module(const struct lys_module *module,
+                              yang_iterate_cb cb, uint16_t flags, void *arg)
 {
        struct lys_node *snode;
+       int ret = YANG_ITER_CONTINUE;
 
        LY_TREE_FOR (module->data, snode) {
-               yang_snodes_iterate(snode, func, flags, arg1, arg2);
+               ret = yang_snodes_iterate_subtree(snode, cb, flags, arg);
+               if (ret == YANG_ITER_STOP)
+                       return ret;
        }
 
        for (uint8_t i = 0; i < module->augment_size; i++) {
-               yang_snodes_iterate(
-                       (const struct lys_node *)&module->augment[i], func,
-                       flags, arg1, arg2);
+               ret = yang_snodes_iterate_subtree(
+                       (const struct lys_node *)&module->augment[i], cb, flags,
+                       arg);
+               if (ret == YANG_ITER_STOP)
+                       return ret;
        }
+
+       return ret;
 }
 
-void yang_all_snodes_iterate(void (*func)(const struct lys_node *, void *,
-                                         void *),
-                            uint16_t flags, void *arg1, void *arg2)
+int yang_snodes_iterate_all(yang_iterate_cb cb, uint16_t flags, void *arg)
 {
        struct yang_module *module;
+       int ret = YANG_ITER_CONTINUE;
+
+       RB_FOREACH (module, yang_modules, &yang_modules) {
+               ret = yang_snodes_iterate_module(module->info, cb, flags, arg);
+               if (ret == YANG_ITER_STOP)
+                       return ret;
+       }
 
-       RB_FOREACH (module, yang_modules, &yang_modules)
-               yang_module_snodes_iterate(module->info, func, flags, arg1,
-                                          arg2);
+       return ret;
 }
 
 void yang_snode_get_path(const struct lys_node *snode, enum yang_path_type type,
@@ -285,7 +348,7 @@ const struct lys_type *yang_snode_get_type(const struct lys_node *snode)
        struct lys_node_leaf *sleaf = (struct lys_node_leaf *)snode;
        struct lys_type *type;
 
-       if (!(sleaf->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
+       if (!CHECK_FLAG(sleaf->nodetype, LYS_LEAF | LYS_LEAFLIST))
                return NULL;
 
        type = &sleaf->type;
@@ -305,6 +368,29 @@ void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
        free(xpath_ptr);
 }
 
+const char *yang_dnode_get_schema_name(const struct lyd_node *dnode,
+                                      const char *xpath_fmt, ...)
+{
+       if (xpath_fmt) {
+               va_list ap;
+               char xpath[XPATH_MAXLEN];
+
+               va_start(ap, xpath_fmt);
+               vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+               va_end(ap);
+
+               dnode = yang_dnode_get(dnode, xpath);
+               if (!dnode) {
+                       flog_err(EC_LIB_YANG_DNODE_NOT_FOUND,
+                                "%s: couldn't find %s", __func__, xpath);
+                       zlog_backtrace(LOG_ERR);
+                       abort();
+               }
+       }
+
+       return dnode->schema->name;
+}
+
 struct lyd_node *yang_dnode_get(const struct lyd_node *dnode,
                                const char *xpath_fmt, ...)
 {
@@ -401,7 +487,7 @@ bool yang_dnode_is_default_recursive(const struct lyd_node *dnode)
        struct lyd_node *root, *next, *dnode_iter;
 
        snode = dnode->schema;
-       if (snode->nodetype & (LYS_LEAF | LYS_LEAFLIST))
+       if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST))
                return yang_dnode_is_default(dnode, NULL);
 
        if (!yang_dnode_is_default(dnode, NULL))
@@ -427,11 +513,12 @@ void yang_dnode_change_leaf(struct lyd_node *dnode, const char *value)
 
 void yang_dnode_set_entry(const struct lyd_node *dnode, void *entry)
 {
-       assert(dnode->schema->nodetype & (LYS_LIST | LYS_CONTAINER));
+       assert(CHECK_FLAG(dnode->schema->nodetype, LYS_LIST | LYS_CONTAINER));
        lyd_set_private(dnode, entry);
 }
 
-void *yang_dnode_get_entry(const struct lyd_node *dnode)
+void *yang_dnode_get_entry(const struct lyd_node *dnode,
+                          bool abort_if_not_found)
 {
        const struct lyd_node *orig_dnode = dnode;
        char xpath[XPATH_MAXLEN];
@@ -450,6 +537,9 @@ void *yang_dnode_get_entry(const struct lyd_node *dnode)
                dnode = dnode->parent;
        }
 
+       if (!abort_if_not_found)
+               return NULL;
+
        yang_dnode_get_path(orig_dnode, xpath, sizeof(xpath));
        flog_err(EC_LIB_YANG_DNODE_NOT_FOUND,
                 "%s: failed to find entry [xpath %s]", __func__, xpath);
@@ -457,12 +547,18 @@ void *yang_dnode_get_entry(const struct lyd_node *dnode)
        abort();
 }
 
-struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx)
+struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx, bool config_only)
 {
        struct lyd_node *dnode;
+       int options;
+
+       if (config_only)
+               options = LYD_OPT_CONFIG;
+       else
+               options = LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB;
 
        dnode = NULL;
-       if (lyd_validate(&dnode, LYD_OPT_CONFIG, ly_ctx) != 0) {
+       if (lyd_validate(&dnode, options, ly_ctx) != 0) {
                /* Should never happen. */
                flog_err(EC_LIB_LIBYANG, "%s: lyd_validate() failed", __func__);
                exit(1);
@@ -478,27 +574,17 @@ struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode)
 
 void yang_dnode_free(struct lyd_node *dnode)
 {
+       while (dnode->parent)
+               dnode = dnode->parent;
        lyd_free_withsiblings(dnode);
 }
 
 struct yang_data *yang_data_new(const char *xpath, const char *value)
 {
-       const struct lys_node *snode;
        struct yang_data *data;
 
-       snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0);
-       if (!snode)
-               snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 1);
-       if (!snode) {
-               flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH,
-                        "%s: unknown data path: %s", __func__, xpath);
-               zlog_backtrace(LOG_ERR);
-               abort();
-       }
-
        data = XCALLOC(MTYPE_YANG_DATA, sizeof(*data));
        strlcpy(data->xpath, xpath, sizeof(data->xpath));
-       data->snode = snode;
        if (value)
                data->value = strdup(value);
 
@@ -570,12 +656,13 @@ void yang_init(void)
        ly_log_options(LY_LOLOG | LY_LOSTORE);
 
        /* Initialize libyang container for native models. */
-       ly_native_ctx = ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD);
+       ly_native_ctx =
+               ly_ctx_new(YANG_MODELS_PATH, LY_CTX_DISABLE_SEARCHDIR_CWD);
        if (!ly_native_ctx) {
                flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
                exit(1);
        }
-       ly_ctx_set_searchdir(ly_native_ctx, YANG_MODELS_PATH);
+       ly_ctx_set_module_imp_clb(ly_native_ctx, yang_module_imp_clb, NULL);
        ly_ctx_set_priv_dup_clb(ly_native_ctx, ly_dup_cb);
 
        /* Detect if the required libyang plugin(s) were loaded successfully. */