]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: use libyang functions if they are present
authorChristian Hopps <chopps@labn.net>
Sat, 6 Jan 2024 11:06:38 +0000 (11:06 +0000)
committerChristian Hopps <chopps@labn.net>
Sun, 7 Jan 2024 15:17:56 +0000 (15:17 +0000)
Add configure.ac tests for libyang functions, if not present supply the
functionality ourselves in yang.[ch]

Signed-off-by: Christian Hopps <chopps@labn.net>
configure.ac
lib/northbound_oper.c
lib/vty.c
lib/yang.c
lib/yang.h
mgmtd/mgmt_txn.c

index a3b0370ec05623c7b68616bd6b62c3de7fd881d3..00cf6451fa47f96b70f325c7852f9cdc115717c3 100644 (file)
@@ -1968,6 +1968,13 @@ AC_CHECK_MEMBER([struct lyd_node.priv], [], [
     Instructions for this are included in the build documentation for your platform at http://docs.frrouting.org/projects/dev-guide/en/latest/building.html])
   ])
 ], [[#include <libyang/libyang.h>]])
+
+AC_CHECK_LIB([yang],[lyd_find_xpath3],[],[AC_MSG_ERROR([m4_normalize([
+libyang missing lyd_find_xpath3])])])
+dnl -- don't add lyd_new_list3 to this list unless bug is fixed upstream
+dnl -- https://github.com/CESNET/libyang/issues/2149
+AC_CHECK_FUNCS([ly_strerrcode ly_strvecode lyd_trim_xpath])
+
 CFLAGS="$ac_cflags_save"
 
 dnl ---------------
index 4e131154e7793a421278640173004e68542a49c8..78106e4e4511ba6168df5a4fa7a3943046c90caa 100644 (file)
@@ -1409,11 +1409,8 @@ static enum nb_error __walk(struct nb_op_yield_state *ys, bool is_resume)
                         */
 
                        if (!node) {
-                               /* NOTE: can also use lyd_new_list2 here when available */
                                err = yang_lyd_new_list(ni[-1].inner, sib,
-                                                       &ni->keys,
-                                                       (struct lyd_node_inner *
-                                                                *)&node);
+                                                       &ni->keys, &node);
                                if (err) {
                                        darr_pop(ys->node_infos);
                                        ret = NB_ERR_RESOURCE;
index a08a3c873590a10f1fa008e991095c0becfa664c..0ee610e3aa524530bbbe29f18d6619a056efcacb 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -3688,88 +3688,9 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format,
        else if (ei->level == LY_LLWRN)
                severity = "warning";
 
-       switch (ei->no) {
-       case LY_SUCCESS:
-               ecode = "ok";
-               break;
-       case LY_EMEM:
-               ecode = "out of memory";
-               break;
-       case LY_ESYS:
-               ecode = "system error";
-               break;
-       case LY_EINVAL:
-               ecode = "invalid value given";
-               break;
-       case LY_EEXIST:
-               ecode = "item exists";
-               break;
-       case LY_ENOTFOUND:
-               ecode = "item not found";
-               break;
-       case LY_EINT:
-               ecode = "operation interrupted";
-               break;
-       case LY_EVALID:
-               ecode = "validation failed";
-               break;
-       case LY_EDENIED:
-               ecode = "access denied";
-               break;
-       case LY_EINCOMPLETE:
-               ecode = "incomplete";
-               break;
-       case LY_ERECOMPILE:
-               ecode = "compile error";
-               break;
-       case LY_ENOT:
-               ecode = "not";
-               break;
-       default:
-       case LY_EPLUGIN:
-       case LY_EOTHER:
-               ecode = "other";
-               break;
-       }
-
-       if (err == LY_EVALID) {
-               switch (ei->vecode) {
-               case LYVE_SUCCESS:
-                       evalid = NULL;
-                       break;
-               case LYVE_SYNTAX:
-                       evalid = "syntax";
-                       break;
-               case LYVE_SYNTAX_YANG:
-                       evalid = "yang-syntax";
-                       break;
-               case LYVE_SYNTAX_YIN:
-                       evalid = "yin-syntax";
-                       break;
-               case LYVE_REFERENCE:
-                       evalid = "reference";
-                       break;
-               case LYVE_XPATH:
-                       evalid = "xpath";
-                       break;
-               case LYVE_SEMANTICS:
-                       evalid = "semantics";
-                       break;
-               case LYVE_SYNTAX_XML:
-                       evalid = "xml-syntax";
-                       break;
-               case LYVE_SYNTAX_JSON:
-                       evalid = "json-syntax";
-                       break;
-               case LYVE_DATA:
-                       evalid = "data";
-                       break;
-               default:
-               case LYVE_OTHER:
-                       evalid = "other";
-                       break;
-               }
-       }
+       ecode = yang_ly_strerrcode(err);
+       if (err == LY_EVALID && ei->vecode != LYVE_SUCCESS)
+               evalid = yang_ly_strvecode(ei->vecode);
 
        switch (format) {
        case LYD_XML:
index b2cc71b309184cb9eefa750e91c8b39d9a41901c..2860108d6454b2d0f8b6de3cb695199fd3fe191b 100644 (file)
@@ -999,86 +999,109 @@ int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys)
        return NB_OK;
 }
 
+/*
+ * ------------------------
+ * Libyang Future Functions
+ * ------------------------
+ *
+ * All these functions are implemented in libyang versions (perhaps unreleased)
+ * beyond what we require currently so we must supply the functionality.
+ */
+
+/*
+ * Safe to remove after libyang v2.1.xxx is required (.144 has a bug so
+ * something > .144) https://github.com/CESNET/libyang/issues/2149
+ */
 LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent,
                         const struct lysc_node *snode,
                         const struct yang_list_keys *list_keys,
-                        struct lyd_node_inner **node)
+                        struct lyd_node **node)
 {
+#if defined(HAVE_LYD_NEW_LIST3) && 0
+       LY_ERR err;
+       const char *keys[LIST_MAXKEYS];
+
+       assert(list_keys->num <= LIST_MAXKEYS);
+       for (int i = 0; i < list_keys->num; i++)
+               keys[i] = list_keys->key[i];
+
+       err = lyd_new_list3(&parent->node, snode->module, snode->name, keys,
+                           NULL, 0, node);
+       return err;
+#else
        struct lyd_node *pnode = &parent->node;
-       struct lyd_node **nodepp = (struct lyd_node **)node;
        const char(*keys)[LIST_MAXKEYLEN] = list_keys->key;
 
-       /*
-        * When
-        * https://github.com/CESNET/libyang/commit/2c1e327c7c2dd3ba12d466a4ebcf62c1c44116c4
-        * is released in libyang we should add a configure.ac check for the
-        * lyd_new_list3 function and use it here.
-        */
+       assert(list_keys->num <= 8);
        switch (list_keys->num) {
        case 0:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp);
+                                   node);
        case 1:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp, keys[0]);
+                                   node, keys[0]);
        case 2:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp, keys[0], keys[1]);
+                                   node, keys[0], keys[1]);
        case 3:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp, keys[0], keys[1], keys[2]);
+                                   node, keys[0], keys[1], keys[2]);
        case 4:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp, keys[0], keys[1], keys[2], keys[3]);
+                                   node, keys[0], keys[1], keys[2], keys[3]);
        case 5:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp, keys[0], keys[1], keys[2], keys[3],
+                                   node, keys[0], keys[1], keys[2], keys[3],
                                    keys[4]);
        case 6:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp, keys[0], keys[1], keys[2], keys[3],
+                                   node, keys[0], keys[1], keys[2], keys[3],
                                    keys[4], keys[5]);
        case 7:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp, keys[0], keys[1], keys[2], keys[3],
+                                   node, keys[0], keys[1], keys[2], keys[3],
                                    keys[4], keys[5], keys[6]);
        case 8:
                return lyd_new_list(pnode, snode->module, snode->name, false,
-                                   nodepp, keys[0], keys[1], keys[2], keys[3],
+                                   node, keys[0], keys[1], keys[2], keys[3],
                                    keys[4], keys[5], keys[6], keys[7]);
        }
        _Static_assert(LIST_MAXKEYS == 8, "max key mismatch in switch unroll");
        /*NOTREACHED*/
        return LY_EINVAL;
+#endif
 }
 
 
-int yang_trim_tree(struct lyd_node *root, const char *xpath)
+/*
+ * Safe to remove after libyang v2.1.144 is required
+ */
+LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath)
 {
-       enum nb_error ret = NB_OK;
        LY_ERR err;
-#if 0
-       err = lyd_trim_xpath(&root, xpath, NULL);
+#ifdef HAVE_LYD_TRIM_XPATH
+       err = lyd_trim_xpath(root, xpath, NULL);
        if (err) {
                flog_err_sys(EC_LIB_LIBYANG,
-                            "cannot obtain specific result for xpath \"%s\"",
-                            xpath);
-               return NB_ERR;
+                            "cannot obtain specific result for xpath \"%s\": %s",
+                            xpath, yang_ly_strerrcode(err));
+               return err;
        }
-       return NB_OK;
+       return LY_SUCCESS;
 #else
        struct lyd_node *node;
        struct lyd_node **remove = NULL;
        struct ly_set *set = NULL;
        uint32_t i;
 
-       err = lyd_find_xpath3(NULL, root, xpath, NULL, &set);
+       *root = lyd_first_sibling(*root);
+
+       err = lyd_find_xpath3(NULL, *root, xpath, NULL, &set);
        if (err) {
                flog_err_sys(EC_LIB_LIBYANG,
-                            "cannot obtain specific result for xpath \"%s\"",
-                            xpath);
-               ret = NB_ERR;
-               goto done;
+                            "cannot obtain specific result for xpath \"%s\": %s",
+                            xpath, yang_ly_strerrcode(err));
+               return err;
        }
        /*
         * Mark keepers and sweep deleting non-keepers.
@@ -1100,7 +1123,7 @@ int yang_trim_tree(struct lyd_node *root, const char *xpath)
        }
 
        darr_ensure_cap(remove, 128);
-       LYD_TREE_DFS_BEGIN (root, node) {
+       LYD_TREE_DFS_BEGIN (*root, node) {
                /*
                 * If this is a direct matching node then include it's subtree
                 * which won't be marked and would otherwise be removed.
@@ -1108,19 +1131,100 @@ int yang_trim_tree(struct lyd_node *root, const char *xpath)
                if (node->priv == (void *)2)
                        LYD_TREE_DFS_continue = 1;
                else if (!node->priv) {
-                       LYD_TREE_DFS_continue = 1;
                        *darr_append(remove) = node;
+                       LYD_TREE_DFS_continue = 1;
                }
-               LYD_TREE_DFS_END(root, node);
+               LYD_TREE_DFS_END(*root, node);
        }
-       darr_foreach_i (remove, i)
+       darr_foreach_i (remove, i) {
+               if (remove[i] == *root)
+                       *root = (*root)->next;
                lyd_free_tree(remove[i]);
+       }
        darr_free(remove);
 
-done:
        if (set)
                ly_set_free(set, NULL);
 
-       return ret;
+       return LY_SUCCESS;
+#endif
+}
+
+/*
+ * Safe to remove after libyang v2.1.128 is required
+ */
+const char *yang_ly_strerrcode(LY_ERR err)
+{
+#ifdef HAVE_LY_STRERRCODE
+       return ly_strerrcode(err);
+#else
+       switch (err) {
+       case LY_SUCCESS:
+               return "ok";
+       case LY_EMEM:
+               return "out of memory";
+       case LY_ESYS:
+               return "system error";
+       case LY_EINVAL:
+               return "invalid value given";
+       case LY_EEXIST:
+               return "item exists";
+       case LY_ENOTFOUND:
+               return "item not found";
+       case LY_EINT:
+               return "operation interrupted";
+       case LY_EVALID:
+               return "validation failed";
+       case LY_EDENIED:
+               return "access denied";
+       case LY_EINCOMPLETE:
+               return "incomplete";
+       case LY_ERECOMPILE:
+               return "compile error";
+       case LY_ENOT:
+               return "not";
+       case LY_EPLUGIN:
+       case LY_EOTHER:
+               return "other";
+       default:
+               return "unknown";
+       }
+#endif
+}
+
+/*
+ * Safe to remove after libyang v2.1.128 is required
+ */
+const char *yang_ly_strvecode(LY_VECODE vecode)
+{
+#ifdef HAVE_LY_STRVECODE
+       return ly_strvecode(vecode);
+#else
+       switch (vecode) {
+       case LYVE_SUCCESS:
+               return "";
+       case LYVE_SYNTAX:
+               return "syntax";
+       case LYVE_SYNTAX_YANG:
+               return "yang-syntax";
+       case LYVE_SYNTAX_YIN:
+               return "yin-syntax";
+       case LYVE_REFERENCE:
+               return "reference";
+       case LYVE_XPATH:
+               return "xpath";
+       case LYVE_SEMANTICS:
+               return "semantics";
+       case LYVE_SYNTAX_XML:
+               return "xml-syntax";
+       case LYVE_SYNTAX_JSON:
+               return "json-syntax";
+       case LYVE_DATA:
+               return "data";
+       case LYVE_OTHER:
+               return "other";
+       default:
+               return "unknown";
+       }
 #endif
 }
index 75dcab2d2af84acc47f390e32c6a34b09a065a1a..dbb7f7163bd2688d4b20a6a585e593b861165556 100644 (file)
@@ -719,11 +719,6 @@ extern int yang_get_key_preds(char *s, const struct lysc_node *snode,
 /* Get YANG keys from an existing dnode */
 extern int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys);
 
-/* Create a new list lyd_node using `yang_list_keys` */
-extern LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent,
-                               const struct lysc_node *snode,
-                               const struct yang_list_keys *keys,
-                               struct lyd_node_inner **node);
 /**
  * yang_resolve_snodes() - Resolve an XPath to matching schema nodes.
  * @ly_ctx: libyang context to operate on.
@@ -744,14 +739,16 @@ extern LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent,
 extern LY_ERR yang_resolve_snode_xpath(struct ly_ctx *ly_ctx, const char *xpath,
                                       struct lysc_node ***snodes, bool *simple);
 
-/**
- * yang_trim_tree() - trim the data tree to the given xpath
- * @root: the data tree
- * @xpath: the xpath to trim @root to.
- *
- * Return: enum nb_error..
+/*
+ * Libyang future functions
  */
-extern int yang_trim_tree(struct lyd_node *root, const char *xpath);
+extern const char *yang_ly_strerrcode(LY_ERR err);
+extern const char *yang_ly_strvecode(LY_VECODE vecode);
+extern LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent,
+                               const struct lysc_node *snode,
+                               const struct yang_list_keys *keys,
+                               struct lyd_node **nodes);
+extern LY_ERR yang_lyd_trim_xpath(struct lyd_node **rootp, const char *xpath);
 
 #ifdef __cplusplus
 }
index 1c644456314473b7ed7811db4961741de5412ae3..297482f0154867dcf142e1706d6d6f50b79702a1 100644 (file)
@@ -1278,8 +1278,9 @@ static int txn_get_tree_data_done(struct mgmt_txn_ctx *txn,
                /*
                 * We have a complex query so Filter results by the xpath query.
                 */
-               ret = yang_trim_tree(get_tree->client_results,
-                                    txn_req->req.get_tree->xpath);
+               if (yang_lyd_trim_xpath(&get_tree->client_results,
+                                       txn_req->req.get_tree->xpath))
+                       ret = NB_ERR;
        }
 
        if (ret == NB_OK)