summaryrefslogtreecommitdiffstats
path: root/lib/yang.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/yang.h')
-rw-r--r--lib/yang.h700
1 files changed, 700 insertions, 0 deletions
diff --git a/lib/yang.h b/lib/yang.h
new file mode 100644
index 0000000..37369c0
--- /dev/null
+++ b/lib/yang.h
@@ -0,0 +1,700 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 NetDEF, Inc.
+ * Renato Westphal
+ */
+
+#ifndef _FRR_YANG_H_
+#define _FRR_YANG_H_
+
+#include "memory.h"
+
+#include <libyang/libyang.h>
+#ifdef HAVE_SYSREPO
+#include <sysrepo.h>
+#endif
+
+#include "yang_wrappers.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Maximum XPath length. */
+#define XPATH_MAXLEN 1024
+
+/* Maximum list key length. */
+#define LIST_MAXKEYS 8
+
+/* Maximum list key length. */
+#define LIST_MAXKEYLEN 128
+
+/* Maximum string length of an YANG value. */
+#define YANG_VALUE_MAXLEN 1024
+
+struct yang_module_embed {
+ struct yang_module_embed *next;
+ const char *mod_name, *mod_rev;
+ const char *sub_mod_name;
+ const char *sub_mod_rev;
+ const char *data;
+ LYS_INFORMAT format;
+};
+
+struct yang_module {
+ RB_ENTRY(yang_module) entry;
+ const char *name;
+ const struct lys_module *info;
+#ifdef HAVE_CONFD
+ int confd_hash;
+#endif
+#ifdef HAVE_SYSREPO
+ sr_subscription_ctx_t *sr_subscription;
+ struct event *sr_thread;
+#endif
+};
+RB_HEAD(yang_modules, yang_module);
+RB_PROTOTYPE(yang_modules, yang_module, entry, yang_module_compare);
+
+struct yang_data {
+ /* XPath identifier of the data element. */
+ char xpath[XPATH_MAXLEN];
+
+ /* Value encoded as a raw string. */
+ char *value;
+};
+
+struct yang_list_keys {
+ /* Number os keys (max: LIST_MAXKEYS). */
+ uint8_t num;
+
+ /* Value encoded as a raw string. */
+ char key[LIST_MAXKEYS][LIST_MAXKEYLEN];
+};
+
+enum yang_path_type {
+ YANG_PATH_SCHEMA = 0,
+ YANG_PATH_DATA,
+};
+
+enum yang_iter_flags {
+ /* Filter non-presence containers. */
+ YANG_ITER_FILTER_NPCONTAINERS = (1<<0),
+
+ /* Filter list keys (leafs). */
+ YANG_ITER_FILTER_LIST_KEYS = (1<<1),
+
+ /* Filter RPC input/output nodes. */
+ YANG_ITER_FILTER_INPUT_OUTPUT = (1<<2),
+};
+
+/* Callback used by the yang_snodes_iterate_*() family of functions. */
+typedef int (*yang_iterate_cb)(const struct lysc_node *snode, void *arg);
+
+/* Callback used by the yang_dnode_iterate() function. */
+typedef int (*yang_dnode_iter_cb)(const struct lyd_node *dnode, void *arg);
+
+/* Return values of the 'yang_iterate_cb' callback. */
+#define YANG_ITER_CONTINUE 0
+#define YANG_ITER_STOP -1
+
+/* Global libyang context for native FRR models. */
+extern struct ly_ctx *ly_native_ctx;
+
+/* Tree of all loaded YANG modules. */
+extern struct yang_modules yang_modules;
+
+/*
+ * Create a new YANG module and load it using libyang. If the YANG module is not
+ * found in the YANG_MODELS_PATH directory, the program will exit with an error.
+ * Once loaded, a YANG module can't be unloaded anymore.
+ *
+ * module_name
+ * Name of the YANG module.
+ *
+ * Returns:
+ * Pointer to newly created YANG module.
+ */
+extern struct yang_module *yang_module_load(const char *module_name);
+
+/*
+ * Load all FRR native YANG models.
+ */
+extern void yang_module_load_all(void);
+
+/*
+ * Find a YANG module by its name.
+ *
+ * module_name
+ * Name of the YANG module.
+ *
+ * Returns:
+ * Pointer to YANG module if found, NULL otherwise.
+ */
+extern struct yang_module *yang_module_find(const char *module_name);
+
+/*
+ * Register a YANG module embedded in the binary file. Should be called
+ * from a constructor function.
+ *
+ * embed
+ * YANG module embedding structure to register. (static global provided
+ * by caller.)
+ */
+extern void yang_module_embed(struct yang_module_embed *embed);
+
+/*
+ * Iterate recursively over all children of a schema node.
+ *
+ * snode
+ * YANG schema node to operate on.
+ *
+ * module
+ * When set, iterate over all nodes of the specified module only.
+ *
+ * cb
+ * Function to call with each schema node.
+ *
+ * flags
+ * YANG_ITER_* flags to control how the iteration is performed.
+ *
+ * arg
+ * Arbitrary argument passed as the second parameter in each call to 'cb'.
+ *
+ * Returns:
+ * The return value of the last called callback.
+ */
+extern int yang_snodes_iterate_subtree(const struct lysc_node *snode,
+ const struct lys_module *module,
+ yang_iterate_cb cb, uint16_t flags,
+ void *arg);
+
+/*
+ * Iterate over all libyang schema nodes from all loaded modules of the
+ * given YANG module.
+ *
+ * module
+ * When set, iterate over all nodes of the specified module only.
+ *
+ * cb
+ * Function to call with each schema node.
+ *
+ * flags
+ * YANG_ITER_* flags to control how the iteration is performed.
+ *
+ * arg
+ * Arbitrary argument passed as the second parameter in each call to 'cb'.
+ *
+ * Returns:
+ * The return value of the last called callback.
+ */
+extern int yang_snodes_iterate(const struct lys_module *module,
+ yang_iterate_cb cb, uint16_t flags, void *arg);
+
+/*
+ * Build schema path or data path of the schema node.
+ *
+ * snode
+ * libyang schema node to be processed.
+ *
+ * type
+ * Specify whether a schema path or a data path should be built.
+ *
+ * xpath
+ * Pointer to previously allocated buffer.
+ *
+ * xpath_len
+ * Size of the xpath buffer.
+ */
+extern void yang_snode_get_path(const struct lysc_node *snode,
+ enum yang_path_type type, char *xpath,
+ size_t xpath_len);
+
+
+/*
+ * Find libyang schema node for the given xpath. Uses `lys_find_xpath`,
+ * returning only the first of a set of nodes -- normally there should only
+ * be one.
+ *
+ * ly_ctx
+ * libyang context to operate on.
+ *
+ * xpath
+ * XPath expression (absolute or relative) to find the schema node for.
+ *
+ * options
+ * Libyang findxpathoptions value (see lys_find_xpath).
+ *
+ * Returns:
+ * The libyang schema node if found, or NULL if not found.
+ */
+extern struct lysc_node *yang_find_snode(struct ly_ctx *ly_ctx,
+ const char *xpath, uint32_t options);
+
+/*
+ * Find first parent schema node which is a presence-container or a list
+ * (non-presence containers are ignored).
+ *
+ * snode
+ * libyang schema node to operate on.
+ *
+ * Returns:
+ * The parent libyang schema node if found, or NULL if not found.
+ */
+extern struct lysc_node *yang_snode_real_parent(const struct lysc_node *snode);
+
+/*
+ * Find first parent schema node which is a list.
+ *
+ * snode
+ * libyang schema node to operate on.
+ *
+ * Returns:
+ * The parent libyang schema node (list) if found, or NULL if not found.
+ */
+extern struct lysc_node *yang_snode_parent_list(const struct lysc_node *snode);
+
+/*
+ * Check if the libyang schema node represents typeless data (e.g. containers,
+ * leafs of type empty, etc).
+ *
+ * snode
+ * libyang schema node to operate on.
+ *
+ * Returns:
+ * true if the schema node represents typeless data, false otherwise.
+ */
+extern bool yang_snode_is_typeless_data(const struct lysc_node *snode);
+
+/*
+ * Get the default value associated to a YANG leaf or leaf-list.
+ *
+ * snode
+ * libyang schema node to operate on.
+ *
+ * Returns:
+ * The default value if it exists, NULL otherwise.
+ */
+extern const char *yang_snode_get_default(const struct lysc_node *snode);
+
+/*
+ * Get the type structure of a leaf of leaf-list. If the type is a leafref, the
+ * final (if there is a chain of leafrefs) target's type is found.
+ *
+ * snode
+ * libyang schema node to operate on.
+ *
+ * Returns:
+ * The found type if the schema node represents a leaf or a leaf-list, NULL
+ * otherwise.
+ */
+extern const struct lysc_type *
+yang_snode_get_type(const struct lysc_node *snode);
+
+/*
+ * Get the number of key nodes for the given list.
+ *
+ * snode
+ * libyang (LYS_LIST) schema node to operate on.
+ *
+ * Returns:
+ * The number of key LYS_LEAFs as children of this list node.
+ */
+extern unsigned int yang_snode_num_keys(const struct lysc_node *snode);
+
+#define LY_FOR_KEYS(snode, skey) \
+ for ((skey) = (const struct lysc_node_leaf *)lysc_node_child((snode)); \
+ (skey); (skey) = (const struct lysc_node_leaf *)((skey)->next)) \
+ if (!lysc_is_key(skey)) { \
+ break; \
+ } else
+
+
+/*
+ * Build data path of the data node.
+ *
+ * dnode
+ * libyang data node to be processed.
+ *
+ * xpath
+ * Pointer to previously allocated buffer.
+ *
+ * xpath_len
+ * Size of the xpath buffer.
+ */
+extern void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
+ size_t xpath_len);
+
+/*
+ * Return the schema name of the given libyang data node.
+ *
+ * dnode
+ * libyang data node.
+ *
+ * xpath_fmt
+ * Optional XPath expression (absolute or relative) to specify a different
+ * data node to operate on in the same data tree.
+ *
+ * Returns:
+ * Schema name of the libyang data node.
+ */
+extern const char *yang_dnode_get_schema_name(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
+
+/*
+ * Find a libyang data node by its YANG data path.
+ *
+ * dnode
+ * Base libyang data node to operate on.
+ *
+ * xpath
+ * Limited XPath (absolute or relative) string. See Path in libyang
+ * documentation for restrictions.
+ *
+ * Returns:
+ * The libyang data node if found, or NULL if not found.
+ */
+extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode,
+ const char *xpath);
+
+/*
+ * Find a libyang data node by its YANG data path.
+ *
+ * dnode
+ * Base libyang data node to operate on.
+ *
+ * xpath_fmt
+ * Limited XPath (absolute or relative) format string. See Path in libyang
+ * documentation for restrictions.
+ *
+ * ...
+ * any parameters for xpath_fmt.
+ *
+ * Returns:
+ * The libyang data node if found, or NULL if not found.
+ */
+extern struct lyd_node *yang_dnode_getf(const struct lyd_node *dnode,
+ const char *path_fmt, ...)
+ PRINTFRR(2, 3);
+
+/*
+ * Check if a libyang data node exists.
+ *
+ * dnode
+ * Base libyang data node to operate on.
+ *
+ * xpath
+ * Limited XPath (absolute or relative) string. See Path in libyang
+ * documentation for restrictions.
+ *
+ * Returns:
+ * true if a libyang data node was found, false otherwise.
+ */
+extern bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath);
+
+/*
+ * Check if a libyang data node exists.
+ *
+ * dnode
+ * Base libyang data node to operate on.
+ *
+ * xpath_fmt
+ * Limited XPath (absolute or relative) format string. See Path in
+ * libyang documentation for restrictions.
+ *
+ * ...
+ * any parameters for xpath_fmt.
+ *
+ * Returns:
+ * true if a libyang data node was found, false otherwise.
+ */
+extern bool yang_dnode_existsf(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+
+/*
+ * Iterate over all libyang data nodes that satisfy an XPath query.
+ *
+ * cb
+ * Function to call with each data node.
+ *
+ * arg
+ * Arbitrary argument passed as the second parameter in each call to 'cb'.
+ *
+ * dnode
+ * Base libyang data node to operate on.
+ *
+ * xpath_fmt
+ * XPath expression (absolute or relative).
+ *
+ * ...
+ * any parameters for xpath_fmt.
+ */
+void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg,
+ const struct lyd_node *dnode, const char *xpath_fmt,
+ ...) PRINTFRR(4, 5);
+
+/*
+ * Check if the libyang data node contains a default value. Non-presence
+ * containers are assumed to always contain a default value.
+ *
+ * dnode
+ * Base libyang data node to operate on.
+ *
+ * xpath
+ * Optional XPath expression (absolute or relative) to specify a different
+ * data node to operate on in the same data tree.
+ *
+ * Returns:
+ * true if the data node contains the default value, false otherwise.
+ */
+extern bool yang_dnode_is_default(const struct lyd_node *dnode,
+ const char *xpath);
+
+/*
+ * Check if the libyang data node contains a default value. Non-presence
+ * containers are assumed to always contain a default value.
+ *
+ * dnode
+ * Base libyang data node to operate on.
+ *
+ * xpath
+ * Optional limited XPath (absolute or relative) format string. See Path in
+ * libyang documentation for restrictions.
+ *
+ * ...
+ * any parameters for xpath_fmt.
+ *
+ * Returns:
+ * true if the data node contains the default value, false otherwise.
+ */
+extern bool yang_dnode_is_defaultf(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+
+/*
+ * Check if the libyang data node and all of its children contain default
+ * values. Non-presence containers are assumed to always contain a default
+ * value.
+ *
+ * dnode
+ * libyang data node to operate on.
+ *
+ * Returns:
+ * true if the data node and all of its children contain default values,
+ * false otherwise.
+ */
+extern bool yang_dnode_is_default_recursive(const struct lyd_node *dnode);
+
+/*
+ * Change the value of a libyang leaf node.
+ *
+ * dnode
+ * libyang data node to operate on.
+ *
+ * value
+ * String representing the new value.
+ */
+extern void yang_dnode_change_leaf(struct lyd_node *dnode, const char *value);
+
+/*
+ * Create a new libyang data node.
+ *
+ * ly_ctx
+ * libyang context to operate on.
+ *
+ * config
+ * Specify whether the data node will contain only configuration data (true)
+ * or both configuration data and state data (false).
+ *
+ * Returns:
+ * Pointer to newly created libyang data node.
+ */
+extern struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx, bool config_only);
+
+/*
+ * Duplicate a libyang data node.
+ *
+ * dnode
+ * libyang data node to duplicate.
+ *
+ * Returns:
+ * Pointer to duplicated libyang data node.
+ */
+extern struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode);
+
+/*
+ * Delete a libyang data node.
+ *
+ * dnode
+ * Pointer to the libyang data node that is going to be deleted along with
+ * the entire tree it belongs to.
+ */
+extern void yang_dnode_free(struct lyd_node *dnode);
+
+/*
+ * Create a new yang_data structure.
+ *
+ * xpath
+ * Data path of the YANG data.
+ *
+ * value
+ * String representing the value of the YANG data.
+ *
+ * Returns:
+ * Pointer to newly created yang_data structure.
+ */
+extern struct yang_data *yang_data_new(const char *xpath, const char *value);
+
+/*
+ * Delete a yang_data structure.
+ *
+ * data
+ * yang_data to delete.
+ */
+extern void yang_data_free(struct yang_data *data);
+
+/*
+ * Create a new linked list of yang_data structures. The list 'del' callback is
+ * initialized appropriately so that the entire list can be deleted safely with
+ * list_delete_and_null().
+ *
+ * Returns:
+ * Pointer to newly created linked list.
+ */
+extern struct list *yang_data_list_new(void);
+
+/*
+ * Find the yang_data structure corresponding to an XPath in a list.
+ *
+ * list
+ * list of yang_data structures to operate on.
+ *
+ * xpath_fmt
+ * XPath to search for (format string).
+ *
+ * Returns:
+ * Pointer to yang_data if found, NULL otherwise.
+ */
+extern struct yang_data *yang_data_list_find(const struct list *list,
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
+
+/*
+ * Create and set up a libyang context (for use by the translator)
+ *
+ * embedded_modules
+ * Specify whether libyang should attempt to look for embedded YANG modules.
+ *
+ * explicit_compile
+ * True if the caller will later call ly_ctx_compile to compile all loaded
+ * modules at once.
+ */
+extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules,
+ bool explicit_compile);
+
+/*
+ * Enable or disable libyang verbose debugging.
+ *
+ * enable
+ * When set to true, enable libyang verbose debugging, otherwise disable it.
+ */
+extern void yang_debugging_set(bool enable);
+
+/*
+ * Print libyang error messages into the provided buffer.
+ *
+ * ly_ctx
+ * libyang context to operate on.
+ *
+ * buf
+ * Buffer to store the libyang error messages.
+ *
+ * buf_len
+ * Size of buf.
+ *
+ * Returns:
+ * The provided buffer.
+ */
+extern const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf,
+ size_t buf_len);
+
+/*
+ * Initialize the YANG subsystem. Should be called only once during the
+ * daemon initialization process.
+ *
+ * embedded_modules
+ * Specify whether libyang should attempt to look for embedded YANG modules.
+ * defer_compile
+ * Hold off on compiling modules until yang_init_loading_complete is called.
+ */
+extern void yang_init(bool embedded_modules, bool defer_compile);
+
+/*
+ * Should be called after yang_init and all yang_module_load()s have been done,
+ * compiles all modules loaded into the yang context.
+ */
+extern void yang_init_loading_complete(void);
+
+/*
+ * Finish the YANG subsystem gracefully. Should be called only when the daemon
+ * is exiting.
+ */
+extern void yang_terminate(void);
+
+/*
+ * API to return the parent dnode having a given schema-node name
+ * Use case: One has to access the parent dnode's private pointer
+ * for a given child node.
+ * For that there is a need to find parent dnode first.
+ *
+ * dnode The starting node to work on
+ *
+ * name The name of container/list schema-node
+ *
+ * Returns The dnode matched with the given name
+ */
+extern const struct lyd_node *
+yang_dnode_get_parent(const struct lyd_node *dnode, const char *name);
+
+
+/*
+ * In some cases there is a need to auto delete the parent nodes
+ * if the given node is last in the list.
+ * It tries to delete all the parents in a given tree in a given module.
+ * The use case is with static routes and route maps
+ * example : ip route 1.1.1.1/32 ens33
+ * ip route 1.1.1.1/32 ens34
+ * After this no ip route 1.1.1.1/32 ens34 came, now staticd
+ * has to find out upto which level it has to delete the dnodes.
+ * For this case it has to send delete nexthop
+ * After this no ip route 1.1.1.1/32 ens33 came, now staticd has to
+ * clear nexthop, path and route nodes.
+ * The same scheme is required for routemaps also
+ * dnode The starting node to work on
+ *
+ * Returns The final parent node selected for deletion
+ */
+extern const struct lyd_node *
+yang_get_subtree_with_no_sibling(const struct lyd_node *dnode);
+
+/* To get the relative position of a node in list */
+extern uint32_t yang_get_list_pos(const struct lyd_node *node);
+
+/* To get the number of elements in a list
+ *
+ * dnode : The head of list
+ * Returns : The number of dnodes present in the list
+ */
+extern uint32_t yang_get_list_elements_count(const struct lyd_node *node);
+
+/* API to check if the given node is last node in the list */
+bool yang_is_last_list_dnode(const struct lyd_node *dnode);
+
+/* API to check if the given node is last node in the data tree level */
+bool yang_is_last_level_dnode(const struct lyd_node *dnode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FRR_YANG_H_ */