back to topotato report
topotato coverage report
Current view: top level - lib - yang_translator.c (source / functions) Hit Total Coverage
Test: test_pim6_prune_propagate.py::PIM6PrunePropagate Lines: 12 256 4.7 %
Date: 2023-02-24 18:39:23 Functions: 8 25 32.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2018  NetDEF, Inc.
       3             :  *                     Renato Westphal
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify it
       6             :  * under the terms of the GNU General Public License as published by the Free
       7             :  * Software Foundation; either version 2 of the License, or (at your option)
       8             :  * any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      13             :  * more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License along
      16             :  * with this program; see the file COPYING; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      18             :  */
      19             : 
      20             : #include <zebra.h>
      21             : 
      22             : #include "log.h"
      23             : #include "lib_errors.h"
      24             : #include "hash.h"
      25             : #include "yang.h"
      26             : #include "yang_translator.h"
      27             : #include "frrstr.h"
      28             : 
      29          44 : DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR, "YANG Translator");
      30          44 : DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR_MODULE, "YANG Translator Module");
      31          44 : DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR_MAPPING, "YANG Translator Mapping");
      32             : 
      33             : /* Generate the yang_translators tree. */
      34           0 : static inline int yang_translator_compare(const struct yang_translator *a,
      35             :                                           const struct yang_translator *b)
      36             : {
      37           0 :         return strcmp(a->family, b->family);
      38             : }
      39           0 : RB_GENERATE(yang_translators, yang_translator, entry, yang_translator_compare)
      40             : 
      41             : struct yang_translators yang_translators = RB_INITIALIZER(&yang_translators);
      42             : 
      43             : /* Separate libyang context for the translator module. */
      44             : static struct ly_ctx *ly_translator_ctx;
      45             : 
      46             : static unsigned int
      47             : yang_translator_validate(struct yang_translator *translator);
      48             : static unsigned int yang_module_nodes_count(const struct lys_module *module);
      49             : 
      50             : struct yang_mapping_node {
      51             :         char xpath_from_canonical[XPATH_MAXLEN];
      52             :         char xpath_from_fmt[XPATH_MAXLEN];
      53             :         char xpath_to_fmt[XPATH_MAXLEN];
      54             : };
      55             : 
      56           0 : static bool yang_mapping_hash_cmp(const void *value1, const void *value2)
      57             : {
      58           0 :         const struct yang_mapping_node *c1 = value1;
      59           0 :         const struct yang_mapping_node *c2 = value2;
      60             : 
      61           0 :         return strmatch(c1->xpath_from_canonical, c2->xpath_from_canonical);
      62             : }
      63             : 
      64           0 : static unsigned int yang_mapping_hash_key(const void *value)
      65             : {
      66           0 :         return string_hash_make(value);
      67             : }
      68             : 
      69           0 : static void *yang_mapping_hash_alloc(void *p)
      70             : {
      71           0 :         struct yang_mapping_node *new, *key = p;
      72             : 
      73           0 :         new = XCALLOC(MTYPE_YANG_TRANSLATOR_MAPPING, sizeof(*new));
      74           0 :         strlcpy(new->xpath_from_canonical, key->xpath_from_canonical,
      75             :                 sizeof(new->xpath_from_canonical));
      76             : 
      77           0 :         return new;
      78             : }
      79             : 
      80           0 : static void yang_mapping_hash_free(void *arg)
      81             : {
      82           0 :         XFREE(MTYPE_YANG_TRANSLATOR_MAPPING, arg);
      83           0 : }
      84             : 
      85             : static struct yang_mapping_node *
      86           0 : yang_mapping_lookup(const struct yang_translator *translator, int dir,
      87             :                     const char *xpath)
      88             : {
      89           0 :         struct yang_mapping_node s;
      90             : 
      91           0 :         strlcpy(s.xpath_from_canonical, xpath, sizeof(s.xpath_from_canonical));
      92           0 :         return hash_lookup(translator->mappings[dir], &s);
      93             : }
      94             : 
      95           0 : static void yang_mapping_add(struct yang_translator *translator, int dir,
      96             :                              const struct lysc_node *snode,
      97             :                              const char *xpath_from_fmt,
      98             :                              const char *xpath_to_fmt)
      99             : {
     100           0 :         struct yang_mapping_node *mapping, s;
     101             : 
     102           0 :         yang_snode_get_path(snode, YANG_PATH_DATA, s.xpath_from_canonical,
     103             :                             sizeof(s.xpath_from_canonical));
     104           0 :         mapping = hash_get(translator->mappings[dir], &s,
     105             :                            yang_mapping_hash_alloc);
     106           0 :         strlcpy(mapping->xpath_from_fmt, xpath_from_fmt,
     107             :                 sizeof(mapping->xpath_from_fmt));
     108           0 :         strlcpy(mapping->xpath_to_fmt, xpath_to_fmt,
     109             :                 sizeof(mapping->xpath_to_fmt));
     110             : 
     111           0 :         const char *keys[] = {"KEY1", "KEY2", "KEY3", "KEY4"};
     112           0 :         char *xpfmt;
     113             : 
     114           0 :         for (unsigned int i = 0; i < array_size(keys); i++) {
     115           0 :                 xpfmt = frrstr_replace(mapping->xpath_from_fmt, keys[i],
     116             :                                        "%[^']");
     117           0 :                 strlcpy(mapping->xpath_from_fmt, xpfmt,
     118             :                         sizeof(mapping->xpath_from_fmt));
     119           0 :                 XFREE(MTYPE_TMP, xpfmt);
     120             :         }
     121             : 
     122           0 :         for (unsigned int i = 0; i < array_size(keys); i++) {
     123           0 :                 xpfmt = frrstr_replace(mapping->xpath_to_fmt, keys[i], "%s");
     124           0 :                 strlcpy(mapping->xpath_to_fmt, xpfmt,
     125             :                         sizeof(mapping->xpath_to_fmt));
     126           0 :                 XFREE(MTYPE_TMP, xpfmt);
     127             :         }
     128           0 : }
     129             : 
     130           0 : struct yang_translator *yang_translator_load(const char *path)
     131             : {
     132           0 :         struct yang_translator *translator;
     133           0 :         struct yang_tmodule *tmodule;
     134           0 :         const char *family;
     135           0 :         struct lyd_node *dnode;
     136           0 :         struct ly_set *set;
     137           0 :         struct listnode *ln;
     138           0 :         LY_ERR err;
     139             : 
     140             :         /* Load module translator (JSON file). */
     141           0 :         err = lyd_parse_data_path(ly_translator_ctx, path, LYD_JSON,
     142             :                                   LYD_PARSE_NO_STATE, LYD_VALIDATE_NO_STATE,
     143             :                                   &dnode);
     144           0 :         if (err) {
     145           0 :                 flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
     146             :                           "%s: lyd_parse_path() failed: %d", __func__, err);
     147           0 :                 return NULL;
     148             :         }
     149           0 :         dnode = yang_dnode_get(dnode,
     150             :                                "/frr-module-translator:frr-module-translator");
     151             :         /*
     152             :          * libyang guarantees the "frr-module-translator" top-level container is
     153             :          * always present since it contains mandatory child nodes.
     154             :          */
     155           0 :         assert(dnode);
     156             : 
     157           0 :         family = yang_dnode_get_string(dnode, "./family");
     158           0 :         translator = yang_translator_find(family);
     159           0 :         if (translator != NULL) {
     160           0 :                 flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
     161             :                           "%s: module translator \"%s\" is loaded already",
     162             :                           __func__, family);
     163           0 :                 return NULL;
     164             :         }
     165             : 
     166           0 :         translator = XCALLOC(MTYPE_YANG_TRANSLATOR, sizeof(*translator));
     167           0 :         strlcpy(translator->family, family, sizeof(translator->family));
     168           0 :         translator->modules = list_new();
     169           0 :         for (size_t i = 0; i < YANG_TRANSLATE_MAX; i++)
     170           0 :                 translator->mappings[i] = hash_create(yang_mapping_hash_key,
     171             :                                                       yang_mapping_hash_cmp,
     172             :                                                       "YANG translation table");
     173           0 :         RB_INSERT(yang_translators, &yang_translators, translator);
     174             : 
     175             :         /* Initialize the translator libyang context. */
     176           0 :         translator->ly_ctx = yang_ctx_new_setup(false, false);
     177           0 :         if (!translator->ly_ctx) {
     178           0 :                 flog_warn(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
     179           0 :                 goto error;
     180             :         }
     181             : 
     182             :         /* Load modules */
     183           0 :         if (lyd_find_xpath(dnode, "./module", &set) != LY_SUCCESS)
     184           0 :                 assert(0); /* XXX libyang2: old ly1 code asserted success */
     185             : 
     186           0 :         for (size_t i = 0; i < set->count; i++) {
     187           0 :                 const char *module_name;
     188             : 
     189           0 :                 tmodule =
     190           0 :                         XCALLOC(MTYPE_YANG_TRANSLATOR_MODULE, sizeof(*tmodule));
     191             : 
     192           0 :                 module_name = yang_dnode_get_string(set->dnodes[i], "./name");
     193           0 :                 tmodule->module = ly_ctx_load_module(translator->ly_ctx,
     194             :                                                      module_name, NULL, NULL);
     195           0 :                 if (!tmodule->module) {
     196           0 :                         flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
     197             :                                   "%s: failed to load module: %s", __func__,
     198             :                                   module_name);
     199           0 :                         ly_set_free(set, NULL);
     200           0 :                         goto error;
     201             :                 }
     202             :         }
     203             : 
     204             :         /* Count nodes in modules. */
     205           0 :         for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) {
     206           0 :                 tmodule->nodes_before_deviations =
     207           0 :                         yang_module_nodes_count(tmodule->module);
     208             :         }
     209             : 
     210             :         /* Load the deviations and count nodes again */
     211           0 :         for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) {
     212           0 :                 const char *module_name = tmodule->module->name;
     213           0 :                 tmodule->deviations = ly_ctx_load_module(
     214             :                         translator->ly_ctx, module_name, NULL, NULL);
     215           0 :                 if (!tmodule->deviations) {
     216           0 :                         flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
     217             :                                   "%s: failed to load module: %s", __func__,
     218             :                                   module_name);
     219           0 :                         ly_set_free(set, NULL);
     220           0 :                         goto error;
     221             :                 }
     222             : 
     223           0 :                 tmodule->nodes_after_deviations =
     224           0 :                         yang_module_nodes_count(tmodule->module);
     225             :         }
     226           0 :         ly_set_free(set, NULL);
     227             : 
     228             :         /* Calculate the coverage. */
     229           0 :         for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) {
     230           0 :                 tmodule->coverage = ((double)tmodule->nodes_after_deviations
     231           0 :                                      / (double)tmodule->nodes_before_deviations)
     232           0 :                                     * 100;
     233             :         }
     234             : 
     235             :         /* Load mappings. */
     236           0 :         if (lyd_find_xpath(dnode, "./module/mappings", &set) != LY_SUCCESS)
     237           0 :                 assert(0); /* XXX libyang2: old ly1 code asserted success */
     238           0 :         for (size_t i = 0; i < set->count; i++) {
     239           0 :                 const char *xpath_custom, *xpath_native;
     240           0 :                 const struct lysc_node *snode_custom, *snode_native;
     241             : 
     242           0 :                 xpath_custom =
     243           0 :                         yang_dnode_get_string(set->dnodes[i], "./custom");
     244             : 
     245           0 :                 snode_custom = lys_find_path(translator->ly_ctx, NULL,
     246             :                                              xpath_custom, 0);
     247           0 :                 if (!snode_custom) {
     248           0 :                         flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
     249             :                                   "%s: unknown data path: %s", __func__,
     250             :                                   xpath_custom);
     251           0 :                         ly_set_free(set, NULL);
     252           0 :                         goto error;
     253             :                 }
     254             : 
     255           0 :                 xpath_native =
     256           0 :                         yang_dnode_get_string(set->dnodes[i], "./native");
     257           0 :                 snode_native =
     258           0 :                         lys_find_path(ly_native_ctx, NULL, xpath_native, 0);
     259           0 :                 if (!snode_native) {
     260           0 :                         flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
     261             :                                   "%s: unknown data path: %s", __func__,
     262             :                                   xpath_native);
     263           0 :                         ly_set_free(set, NULL);
     264           0 :                         goto error;
     265             :                 }
     266             : 
     267           0 :                 yang_mapping_add(translator, YANG_TRANSLATE_TO_NATIVE,
     268             :                                  snode_custom, xpath_custom, xpath_native);
     269           0 :                 yang_mapping_add(translator, YANG_TRANSLATE_FROM_NATIVE,
     270             :                                  snode_native, xpath_native, xpath_custom);
     271             :         }
     272           0 :         ly_set_free(set, NULL);
     273             : 
     274             :         /* Validate mappings. */
     275           0 :         if (yang_translator_validate(translator) != 0)
     276           0 :                 goto error;
     277             : 
     278           0 :         yang_dnode_free(dnode);
     279             : 
     280           0 :         return translator;
     281             : 
     282           0 : error:
     283           0 :         yang_dnode_free(dnode);
     284           0 :         yang_translator_unload(translator);
     285             : 
     286           0 :         return NULL;
     287             : }
     288             : 
     289           0 : static void yang_tmodule_delete(struct yang_tmodule *tmodule)
     290             : {
     291           0 :         XFREE(MTYPE_YANG_TRANSLATOR_MODULE, tmodule);
     292           0 : }
     293             : 
     294           0 : void yang_translator_unload(struct yang_translator *translator)
     295             : {
     296           0 :         for (size_t i = 0; i < YANG_TRANSLATE_MAX; i++)
     297           0 :                 hash_clean(translator->mappings[i], yang_mapping_hash_free);
     298           0 :         translator->modules->del = (void (*)(void *))yang_tmodule_delete;
     299           0 :         list_delete(&translator->modules);
     300           0 :         ly_ctx_destroy(translator->ly_ctx);
     301           0 :         RB_REMOVE(yang_translators, &yang_translators, translator);
     302           0 :         XFREE(MTYPE_YANG_TRANSLATOR, translator);
     303           0 : }
     304             : 
     305           0 : struct yang_translator *yang_translator_find(const char *family)
     306             : {
     307           0 :         struct yang_translator s;
     308             : 
     309           0 :         strlcpy(s.family, family, sizeof(s.family));
     310           0 :         return RB_FIND(yang_translators, &yang_translators, &s);
     311             : }
     312             : 
     313             : enum yang_translate_result
     314           0 : yang_translate_xpath(const struct yang_translator *translator, int dir,
     315             :                      char *xpath, size_t xpath_len)
     316             : {
     317           0 :         struct ly_ctx *ly_ctx;
     318           0 :         const struct lysc_node *snode;
     319           0 :         struct yang_mapping_node *mapping;
     320           0 :         char xpath_canonical[XPATH_MAXLEN];
     321           0 :         char keys[4][LIST_MAXKEYLEN];
     322           0 :         int n;
     323             : 
     324           0 :         if (dir == YANG_TRANSLATE_TO_NATIVE)
     325           0 :                 ly_ctx = translator->ly_ctx;
     326             :         else
     327           0 :                 ly_ctx = ly_native_ctx;
     328             : 
     329           0 :         snode = lys_find_path(ly_ctx, NULL, xpath, 0);
     330           0 :         if (!snode) {
     331           0 :                 flog_warn(EC_LIB_YANG_TRANSLATION_ERROR,
     332             :                           "%s: unknown data path: %s", __func__, xpath);
     333           0 :                 return YANG_TRANSLATE_FAILURE;
     334             :         }
     335             : 
     336           0 :         yang_snode_get_path(snode, YANG_PATH_DATA, xpath_canonical,
     337             :                             sizeof(xpath_canonical));
     338           0 :         mapping = yang_mapping_lookup(translator, dir, xpath_canonical);
     339           0 :         if (!mapping)
     340             :                 return YANG_TRANSLATE_NOTFOUND;
     341             : 
     342             : #pragma GCC diagnostic push
     343             : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
     344             :         /* processing format strings from mapping node... */
     345           0 :         n = sscanf(xpath, mapping->xpath_from_fmt, keys[0], keys[1], keys[2],
     346             :                    keys[3]);
     347             : #pragma GCC diagnostic pop
     348           0 :         if (n < 0) {
     349           0 :                 flog_warn(EC_LIB_YANG_TRANSLATION_ERROR,
     350             :                           "%s: sscanf() failed: %s", __func__,
     351             :                           safe_strerror(errno));
     352           0 :                 return YANG_TRANSLATE_FAILURE;
     353             :         }
     354             : 
     355             : #pragma GCC diagnostic push
     356             : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
     357             :         /* processing format strings from mapping node... */
     358           0 :         snprintf(xpath, xpath_len, mapping->xpath_to_fmt, keys[0], keys[1],
     359             :                  keys[2], keys[3]);
     360             : #pragma GCC diagnostic pop
     361             : 
     362           0 :         return YANG_TRANSLATE_SUCCESS;
     363             : }
     364             : 
     365           0 : int yang_translate_dnode(const struct yang_translator *translator, int dir,
     366             :                          struct lyd_node **dnode)
     367             : {
     368           0 :         struct ly_ctx *ly_ctx;
     369           0 :         struct lyd_node *new;
     370           0 :         struct lyd_node *root, *dnode_iter;
     371             : 
     372             :         /* Create new libyang data node to hold the translated data. */
     373           0 :         if (dir == YANG_TRANSLATE_TO_NATIVE)
     374           0 :                 ly_ctx = ly_native_ctx;
     375             :         else
     376           0 :                 ly_ctx = translator->ly_ctx;
     377           0 :         new = yang_dnode_new(ly_ctx, false);
     378             : 
     379             :         /* Iterate over all nodes from the data tree. */
     380           0 :         LY_LIST_FOR (*dnode, root) {
     381           0 :                 LYD_TREE_DFS_BEGIN (root, dnode_iter) {
     382           0 :                         char xpath[XPATH_MAXLEN];
     383           0 :                         enum yang_translate_result ret;
     384             : 
     385           0 :                         yang_dnode_get_path(dnode_iter, xpath, sizeof(xpath));
     386           0 :                         ret = yang_translate_xpath(translator, dir, xpath,
     387             :                                                    sizeof(xpath));
     388           0 :                         switch (ret) {
     389             :                         case YANG_TRANSLATE_SUCCESS:
     390             :                                 break;
     391           0 :                         case YANG_TRANSLATE_NOTFOUND:
     392           0 :                                 goto next;
     393           0 :                         case YANG_TRANSLATE_FAILURE:
     394           0 :                                 goto error;
     395             :                         }
     396             : 
     397             :                         /* Create new node in the tree of translated data. */
     398           0 :                         if (lyd_new_path(new, ly_ctx, xpath,
     399             :                                          (void *)yang_dnode_get_string(
     400             :                                                  dnode_iter, NULL),
     401             :                                          LYD_NEW_PATH_UPDATE, NULL)) {
     402           0 :                                 flog_err(EC_LIB_LIBYANG,
     403             :                                          "%s: lyd_new_path() failed", __func__);
     404           0 :                                 goto error;
     405             :                         }
     406             : 
     407           0 :                 next:
     408           0 :                         LYD_TREE_DFS_END(root, dnode_iter);
     409             :                 }
     410             :         }
     411             : 
     412             :         /* Replace dnode by the new translated dnode. */
     413           0 :         yang_dnode_free(*dnode);
     414           0 :         *dnode = new;
     415             : 
     416           0 :         return YANG_TRANSLATE_SUCCESS;
     417             : 
     418           0 : error:
     419           0 :         yang_dnode_free(new);
     420             : 
     421           0 :         return YANG_TRANSLATE_FAILURE;
     422             : }
     423             : 
     424             : struct translator_validate_args {
     425             :         struct yang_translator *translator;
     426             :         unsigned int errors;
     427             : };
     428             : 
     429           0 : static int yang_translator_validate_cb(const struct lysc_node *snode_custom,
     430             :                                        void *arg)
     431             : {
     432           0 :         struct translator_validate_args *args = arg;
     433           0 :         struct yang_mapping_node *mapping;
     434           0 :         const struct lysc_node *snode_native;
     435           0 :         const struct lysc_type *stype_custom, *stype_native;
     436           0 :         char xpath[XPATH_MAXLEN];
     437             : 
     438           0 :         yang_snode_get_path(snode_custom, YANG_PATH_DATA, xpath, sizeof(xpath));
     439           0 :         mapping = yang_mapping_lookup(args->translator,
     440             :                                       YANG_TRANSLATE_TO_NATIVE, xpath);
     441           0 :         if (!mapping) {
     442           0 :                 flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
     443             :                           "%s: missing mapping for \"%s\"", __func__, xpath);
     444           0 :                 args->errors += 1;
     445           0 :                 return YANG_ITER_CONTINUE;
     446             :         }
     447             : 
     448           0 :         snode_native =
     449           0 :                 lys_find_path(ly_native_ctx, NULL, mapping->xpath_to_fmt, 0);
     450           0 :         assert(snode_native);
     451             : 
     452             :         /* Check if the YANG types are compatible. */
     453           0 :         stype_custom = yang_snode_get_type(snode_custom);
     454           0 :         stype_native = yang_snode_get_type(snode_native);
     455           0 :         if (stype_custom && stype_native) {
     456           0 :                 if (stype_custom->basetype != stype_native->basetype) {
     457           0 :                         flog_warn(
     458             :                                 EC_LIB_YANG_TRANSLATOR_LOAD,
     459             :                                 "%s: YANG types are incompatible (xpath: \"%s\")",
     460             :                                 __func__, xpath);
     461           0 :                         args->errors += 1;
     462           0 :                         return YANG_ITER_CONTINUE;
     463             :                 }
     464             : 
     465             :                 /* TODO: check if the value spaces are identical. */
     466             :         }
     467             : 
     468             :         return YANG_ITER_CONTINUE;
     469             : }
     470             : 
     471             : /*
     472             :  * Check if the modules from the translator have a mapping for all of their
     473             :  * schema nodes (after loading the deviations).
     474             :  */
     475           0 : static unsigned int yang_translator_validate(struct yang_translator *translator)
     476             : {
     477           0 :         struct yang_tmodule *tmodule;
     478           0 :         struct listnode *ln;
     479           0 :         struct translator_validate_args args;
     480             : 
     481           0 :         args.translator = translator;
     482           0 :         args.errors = 0;
     483             : 
     484           0 :         for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) {
     485           0 :                 yang_snodes_iterate(tmodule->module,
     486             :                                     yang_translator_validate_cb,
     487             :                                     YANG_ITER_FILTER_NPCONTAINERS
     488             :                                             | YANG_ITER_FILTER_LIST_KEYS
     489             :                                             | YANG_ITER_FILTER_INPUT_OUTPUT,
     490             :                                     &args);
     491             :         }
     492             : 
     493           0 :         if (args.errors)
     494           0 :                 flog_warn(
     495             :                         EC_LIB_YANG_TRANSLATOR_LOAD,
     496             :                         "%s: failed to validate \"%s\" module translator: %u error(s)",
     497             :                         __func__, translator->family, args.errors);
     498             : 
     499           0 :         return args.errors;
     500             : }
     501             : 
     502           0 : static int yang_module_nodes_count_cb(const struct lysc_node *snode, void *arg)
     503             : {
     504           0 :         unsigned int *total = arg;
     505             : 
     506           0 :         *total += 1;
     507             : 
     508           0 :         return YANG_ITER_CONTINUE;
     509             : }
     510             : 
     511             : /* Calculate the number of nodes for the given module. */
     512           0 : static unsigned int yang_module_nodes_count(const struct lys_module *module)
     513             : {
     514           0 :         unsigned int total = 0;
     515             : 
     516           0 :         yang_snodes_iterate(module, yang_module_nodes_count_cb,
     517             :                             YANG_ITER_FILTER_NPCONTAINERS
     518             :                                     | YANG_ITER_FILTER_LIST_KEYS
     519             :                                     | YANG_ITER_FILTER_INPUT_OUTPUT,
     520             :                             &total);
     521             : 
     522           0 :         return total;
     523             : }
     524             : 
     525          12 : void yang_translator_init(void)
     526             : {
     527          12 :         ly_translator_ctx = yang_ctx_new_setup(true, false);
     528          12 :         if (!ly_translator_ctx) {
     529           0 :                 flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
     530           0 :                 exit(1);
     531             :         }
     532             : 
     533          12 :         if (!ly_ctx_load_module(ly_translator_ctx, "frr-module-translator",
     534             :                                 NULL, NULL)) {
     535           0 :                 flog_err(
     536             :                         EC_LIB_YANG_MODULE_LOAD,
     537             :                         "%s: failed to load the \"frr-module-translator\" module",
     538             :                         __func__);
     539           0 :                 exit(1);
     540             :         }
     541          12 : }
     542             : 
     543          24 : void yang_translator_terminate(void)
     544             : {
     545          24 :         while (!RB_EMPTY(yang_translators, &yang_translators)) {
     546           0 :                 struct yang_translator *translator;
     547             : 
     548           0 :                 translator = RB_ROOT(yang_translators, &yang_translators);
     549           0 :                 yang_translator_unload(translator);
     550             :         }
     551             : 
     552          24 :         ly_ctx_destroy(ly_translator_ctx);
     553          24 : }

Generated by: LCOV version v1.16-topotato