blob: 0b2a5bdd319610f79c9aa9a5d54008103920338d [file] [log] [blame]
Radek Krejcid7e8a622018-10-29 15:54:55 +01001/**
Radek Krejci0935f412019-08-20 16:15:18 +02002 * @file plugins_exts.h
Radek Krejcid7e8a622018-10-29 15:54:55 +01003 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief libyang support for YANG extensions implementation.
5 *
Radek Krejci0935f412019-08-20 16:15:18 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
Radek Krejcid7e8a622018-10-29 15:54:55 +01007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Radek Krejci0935f412019-08-20 16:15:18 +020015#ifndef LY_PLUGINS_EXTS_H_
16#define LY_PLUGINS_EXTS_H_
Radek Krejcid7e8a622018-10-29 15:54:55 +010017
Radek Krejci0e59c312019-08-15 15:34:15 +020018#include "set.h"
19#include "tree_schema.h"
20
Radek Krejcid7e8a622018-10-29 15:54:55 +010021#ifdef __cplusplus
22extern "C" {
23#endif
24
Radek Krejci0e59c312019-08-15 15:34:15 +020025
Radek Krejcid7e8a622018-10-29 15:54:55 +010026/**
27 * @defgroup extensions YANG Extensions
28 *
29 * @{
30 */
31
32/**
Radek Krejci0935f412019-08-20 16:15:18 +020033 * @brief Extensions API version
34 */
35#define LYEXT_API_VERSION 1
36
37/**
38 * @brief Macro to store version of extension plugins API in the plugins.
39 * It is matched when the plugin is being loaded by libyang.
40 */
41#define LYEXT_VERSION_CHECK int lyext_api_version = LYEXT_API_VERSION;
42
43/**
Radek Krejci0e59c312019-08-15 15:34:15 +020044 * @defgroup extensionscompile YANG Extensions - Compilation Helpers
45 * @ingroup extensions
46 * @brief Helper functions to compile (via lyext_clb_compile callback) statements inside the extension instance.
47 *
48 * NOTE: There is a lot of useful static functions in the tree_schema_compile.c which could be provided here. Since we don't want
49 * to have a large API with functions which will be never used, we provide here just the functions which are evidently needed.
50 * If you, as an extension plugin author, need to make some of the compile functions available, please contact libyang maintainers
51 * via the GITHUB issue tracker.
52 *
53 * @{
Radek Krejcid7e8a622018-10-29 15:54:55 +010054 */
Radek Krejcid7e8a622018-10-29 15:54:55 +010055
56/**
Radek Krejcic5ad9652019-09-11 11:31:51 +020057 * @defgroup scflags Schema compile flags
58 * @ingroup schematree
59 *
60 * @{
61 */
62#define LYSC_OPT_RPC_INPUT LYS_CONFIG_W /**< Internal option when compiling schema tree of RPC/action input */
63#define LYSC_OPT_RPC_OUTPUT LYS_CONFIG_R /**< Internal option when compiling schema tree of RPC/action output */
64#define LYSC_OPT_RPC_MASK LYS_CONFIG_MASK /**< mask for the internal RPC options */
65#define LYSC_OPT_FREE_SP 0x04 /**< Free the input printable schema */
66#define LYSC_OPT_INTERNAL 0x08 /**< Internal compilation caused by dependency */
67#define LYSC_OPT_NOTIFICATION 0x10 /**< Internal option when compiling schema tree of Notification */
68
69#define LYSC_OPT_GROUPING 0x20 /** Compiling (validation) of a non-instantiated grouping.
70 In this case not all the restrictions are checked since they can be valid only
71 in the real placement of the grouping. TODO - what specifically is not done */
72/** @} scflags */
73
74/**
Radek Krejci0e59c312019-08-15 15:34:15 +020075 * @brief internal context for compilation
Radek Krejcid7e8a622018-10-29 15:54:55 +010076 */
Radek Krejci0e59c312019-08-15 15:34:15 +020077struct lysc_ctx {
78 struct ly_ctx *ctx;
79 struct lys_module *mod;
80 struct lys_module *mod_def; /**< context module for the definitions of the nodes being currently
81 processed - groupings are supposed to be evaluated in place where
82 defined, but its content instances are supposed to be placed into
83 the target module (mod) */
84 struct ly_set groupings; /**< stack for groupings circular check */
85 struct ly_set unres; /**< to validate leafref's target and xpath of when/must */
86 struct ly_set dflts; /**< set of incomplete default values */
87 struct ly_set tpdf_chain;
88 uint16_t path_len;
89 int options; /**< various @ref scflags. */
90#define LYSC_CTX_BUFSIZE 4078
91 char path[LYSC_CTX_BUFSIZE];
92};
Radek Krejcid7e8a622018-10-29 15:54:55 +010093
Radek Krejci0e59c312019-08-15 15:34:15 +020094/**
Radek Krejcid6b76452019-09-03 17:03:03 +020095 * @brief Possible cardinalities of the YANG statements.
96 *
97 * Used in extensions plugins to define cardinalities of the extension instance substatements.
98 */
99enum ly_stmt_cardinality {
100 LY_STMT_CARD_OPT, /* 0..1 */
101 LY_STMT_CARD_MAND, /* 1 */
102 LY_STMT_CARD_SOME, /* 1..n */
103 LY_STMT_CARD_ANY /* 0..n */
104};
105
106/**
107 * @brief Description of the extension instance substatements.
108 *
109 * Provided by extensions plugins to libyang's lyext_compile_stmts() to be able to correctly compile the content of extension instances.
Radek Krejci335332a2019-09-05 13:03:35 +0200110 * Note that order of the defined records matters - just follow the values of enum ly_stmt and order the records from lower to higher values.
Radek Krejcid6b76452019-09-03 17:03:03 +0200111 */
112struct lysc_ext_substmt {
113 enum ly_stmt stmt; /**< allowed substatement */
114 enum ly_stmt_cardinality cardinality; /**< cardinality of the substatement */
115 void *storage; /**< pointer to the storage of the compiled statement according to the specific
116 lysc_ext_substmt::stmt and lysc_ext_substmt::cardinality */
117};
118
119/**
120 * @brief Compile substatements of an extension instance.
Radek Krejci38d85362019-09-05 16:26:38 +0200121 * TODO
Radek Krejcid6b76452019-09-03 17:03:03 +0200122 */
123LY_ERR lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext, struct lysc_ext_substmt *substmts);
124
125/**
Radek Krejci38d85362019-09-05 16:26:38 +0200126 * @brief Free the extension instance's data compiled with lys_compile_extension_instance().
127 * TODO
128 */
129void lysc_extension_instance_free(struct ly_ctx *ctx, struct lysc_ext_substmt *substmts);
130
131/**
Michal Vasko6f4cbb62020-02-28 11:15:47 +0100132 * @brief Duplicate the compiled extension (definition) structure.
133 * TODO should this be in API? currently required for nacm_compile()
134 * Instead of duplicating memory, the reference counter in the @p orig is increased.
135 *
136 * @param[in] orig The extension structure to duplicate.
137 * @return The duplicated structure to use.
138 */
139struct lysc_ext *lysc_ext_dup(struct lysc_ext *orig);
140
141/**
Radek Krejci0e59c312019-08-15 15:34:15 +0200142 * @brief Update path in the compile context, which is used for logging where the compilation failed.
143 *
144 * @param[in] ctx Compile context with the path.
145 * @param[in] parent Parent of the current node to check difference of the node's module. The current module is taken from lysc_ctx::mod.
146 * @param[in] name Name of the node to update path with. If NULL, the last segment is removed. If the format is `{keyword}`, the following
147 * call updates the segment to the form `{keyword='name'}` (to remove this compound segment, 2 calls with NULL @p name must be used).
148 */
149void lysc_update_path(struct lysc_ctx *ctx, struct lysc_node *parent, const char *name);
150
151/** @} extensionscompile */
152
153/**
154 * @brief Callback to compile extension from the lysp_ext_instance to the lysc_ext_instance. The later structure is generally prepared
155 * and only the extension specific data are supposed to be added (if any).
156 *
157 * @param[in] cctx Current compile context.
158 * @param[in] p_ext Parsed extension instance data.
159 * @param[in,out] c_ext Prepared compiled extension instance structure where an addition, extension-specific, data are supposed to be placed
160 * for later use (data validation or use of external tool).
161 * @return LY_SUCCESS in case of success.
162 * @return LY_EVALID in case of non-conforming parsed data.
163 */
164typedef LY_ERR (*lyext_clb_compile)(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext);
165
166/**
167 * @brief Callback to free the extension specific data created by the lyext_clb_compile callback of the same extension plugin.
168 *
Radek Krejci38d85362019-09-05 16:26:38 +0200169 * @param[in] ctx libyang context.
Radek Krejci0e59c312019-08-15 15:34:15 +0200170 * @param[in,out] ext Compiled extension structure where the data to free are placed.
171 */
Radek Krejci38d85362019-09-05 16:26:38 +0200172typedef void (*lyext_clb_free)(struct ly_ctx *ctx, struct lysc_ext_instance *ext);
Radek Krejci0e59c312019-08-15 15:34:15 +0200173
174/**
175 * @brief Callback to decide if data instance is valid according to the schema.
176 *
177 * The callback is used only for the extension instances placed in the following parent statements
178 * (which is specified as lysc_ext_instance::parent_type):
179 * - LYEXT_PAR_NODE - @p node is instance of the schema node where the extension instance was specified.
180 * - LYEXT_PAR_TPDF - @p node is instance of the schema node with the value of the typedef's type where the extension instance was specified.
181 * - LYEXT_PAR_TYPE - @p node is instance of the schema node with the value of the type where the extension instance was specified.
182 * - LYEXT_PAR_TYPE_BIT - @p node is instance of the schema node with the value of the bit where the extension instance was specified.
183 * - LYEXT_PAR_TYPE_ENUM - @p node is instance of the schema node with the value of the enum where the extension instance was specified.
184 *
185 * @param[in] ext Extension instance to be checked.
186 * @param[in] node Data node, where the extension data are supposed to be placed.
187 *
188 * @return LY_SUCCESS on data validation success.
189 * @return LY_EVALID in case the validation fails.
190 */
191typedef LY_ERR (*lyext_clb_data_validation)(struct lysc_ext_instance *ext, struct lyd_node *node);
192
193/**
194 * @brief Extension plugin implementing various aspects of a YANG extension
195 */
196struct lyext_plugin {
197 const char *id; /**< Plugin identification (mainly for distinguish incompatible versions of the plugins for external tools) */
198 lyext_clb_compile compile; /**< Callback to compile extension instance from the parsed data */
199 lyext_clb_data_validation validate; /**< Callback to decide if data instance is valid according to the schema. */
200 /* TODO printers? (schema/data) */
201 lyext_clb_free free; /**< Free the extension instance specific data created by lyext_plugin::compile callback */
202};
203
Radek Krejci0935f412019-08-20 16:15:18 +0200204struct lyext_plugins_list {
205 const char *module; /**< name of the module where the extension is defined */
206 const char *revision; /**< optional module revision - if not specified, the plugin applies to any revision,
207 which is not an optimal approach due to a possible future revisions of the module.
208 Instead, there should be defined multiple items in the plugins list, each with the
209 different revision, but all with the same pointer to the plugin extension. The
210 only valid use case for the NULL revision is the case the module has no revision. */
211 const char *name; /**< name of the extension */
212 struct lyext_plugin *plugin; /**< plugin for the extension */
213};
214
215
216/**
217 * @brief Provide a log message from an extension plugin.
218 *
219 * @param[in] ext Compiled extension structure providing generic information about the extension/plugin causing the message.
220 * @param[in] level Log message level (error, warning, etc.)
221 * @param[in] err_no Error type code.
222 * @param[in] path Path relevant to the message.
223 * @param[in] format Format string to print.
224 */
225void lyext_log(const struct lysc_ext_instance *ext, LY_LOG_LEVEL level, LY_ERR err_no, const char *path, const char *format, ...);
226
Radek Krejci0e59c312019-08-15 15:34:15 +0200227/** @} extensions */
Radek Krejcid7e8a622018-10-29 15:54:55 +0100228
229#ifdef __cplusplus
230}
231#endif
232
Radek Krejci0935f412019-08-20 16:15:18 +0200233#endif /* LY_PLUGINS_EXTS_H_ */