blob: 9ad46a2c873c08880d7436f5e53adfd149532224 [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 Krejci535ea9f2020-05-29 16:01:05 +020018#include "log.h"
Radek Krejci0e59c312019-08-15 15:34:15 +020019#include "tree_schema.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020020
21struct ly_ctx;
22struct lyd_node;
Radek Krejci47fab892020-11-05 17:02:41 +010023struct lysc_ctx;
Radek Krejci0e59c312019-08-15 15:34:15 +020024
Radek Krejcid7e8a622018-10-29 15:54:55 +010025#ifdef __cplusplus
26extern "C" {
27#endif
28
29/**
30 * @defgroup extensions YANG Extensions
31 *
32 * @{
33 */
34
35/**
Radek Krejci0935f412019-08-20 16:15:18 +020036 * @brief Extensions API version
37 */
38#define LYEXT_API_VERSION 1
39
40/**
41 * @brief Macro to store version of extension plugins API in the plugins.
42 * It is matched when the plugin is being loaded by libyang.
43 */
Radek Krejci1deb5be2020-08-26 16:43:36 +020044#define LYEXT_VERSION_CHECK uint32_t lyext_api_version = LYEXT_API_VERSION;
Radek Krejci0935f412019-08-20 16:15:18 +020045
46/**
Radek Krejci0e59c312019-08-15 15:34:15 +020047 * @defgroup extensionscompile YANG Extensions - Compilation Helpers
48 * @ingroup extensions
49 * @brief Helper functions to compile (via lyext_clb_compile callback) statements inside the extension instance.
50 *
51 * 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
52 * to have a large API with functions which will be never used, we provide here just the functions which are evidently needed.
53 * If you, as an extension plugin author, need to make some of the compile functions available, please contact libyang maintainers
54 * via the GITHUB issue tracker.
55 *
56 * @{
Radek Krejcid7e8a622018-10-29 15:54:55 +010057 */
Radek Krejcid7e8a622018-10-29 15:54:55 +010058
59/**
Radek Krejcid6b76452019-09-03 17:03:03 +020060 * @brief Possible cardinalities of the YANG statements.
61 *
62 * Used in extensions plugins to define cardinalities of the extension instance substatements.
63 */
64enum ly_stmt_cardinality {
65 LY_STMT_CARD_OPT, /* 0..1 */
66 LY_STMT_CARD_MAND, /* 1 */
67 LY_STMT_CARD_SOME, /* 1..n */
68 LY_STMT_CARD_ANY /* 0..n */
69};
70
71/**
72 * @brief Description of the extension instance substatements.
73 *
Radek Krejci8678fa42020-08-18 16:07:28 +020074 * Provided by extensions plugins to libyang to be able to correctly compile the content of extension instances.
75 * Note that order of the defined records matters - just follow the values of ::ly_stmt and order the records from lower to higher values.
Radek Krejcid6b76452019-09-03 17:03:03 +020076 */
77struct lysc_ext_substmt {
78 enum ly_stmt stmt; /**< allowed substatement */
79 enum ly_stmt_cardinality cardinality; /**< cardinality of the substatement */
80 void *storage; /**< pointer to the storage of the compiled statement according to the specific
81 lysc_ext_substmt::stmt and lysc_ext_substmt::cardinality */
82};
83
84/**
Radek Krejciadcf63d2021-02-09 10:21:18 +010085 * @brief Types of the YANG printers
86 */
87enum lys_ypr_schema_type {
88 LYS_YPR_PARSED, /**< YANG printer of the parsed schema */
89 LYS_YPR_COMPILED /**< YANG printer of the compiled schema */
90};
91
92/**
93 * @brief YANG printer context.
94 */
95struct lys_ypr_ctx {
96 struct ly_out *out; /**< output specification */
97 uint16_t level; /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
98 uint32_t options; /**< Schema output options (see @ref schemaprinterflags). */
99 const struct lys_module *module; /**< schema to print */
100 enum lys_ypr_schema_type schema; /**< type of the schema to print */
101};
102
103/**
Radek Krejcid6b76452019-09-03 17:03:03 +0200104 * @brief Compile substatements of an extension instance.
Radek Krejci38d85362019-09-05 16:26:38 +0200105 * TODO
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100106 * @return LY_ENOT if the extension is disabled and should be ignored.
Radek Krejcid6b76452019-09-03 17:03:03 +0200107 */
Radek Krejci6b88a462021-02-17 12:39:34 +0100108LY_ERR lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext_p, struct lysc_ext_instance *ext);
Radek Krejcid6b76452019-09-03 17:03:03 +0200109
110/**
Radek Krejciadcf63d2021-02-09 10:21:18 +0100111 * @brief Print substatements of an extension instance
112 *
113 * Generic function to access YANG printer functions from the extension plugins (::lyext_clb_schema_printer).
114 *
115 * @param[in] ctx YANG printer context to provide output handler and other information for printing.
116 * @param[in] ext The compiled extension instance to access the extensions and substatements data.
117 * @param[in, out] flag Flag to be shared with the caller regarding the opening brackets - 0 if the '{' not yet printed,
118 * 1 otherwise.
119 */
120void lysc_print_extension_instance(struct lys_ypr_ctx *ctx, const struct lysc_ext_instance *ext, ly_bool *flag);
121
122/**
Radek Krejci8678fa42020-08-18 16:07:28 +0200123 * @brief Free the extension instance's data compiled with ::lys_compile_extension_instance().
Radek Krejci1b2eef82021-02-17 11:17:27 +0100124 *
125 * @param[in] libyang context
126 * @param[in] substmts The sized array of extension instance's substatements. The whole array is freed except the storage
127 * places which are expected to be covered by the extension plugin.
Radek Krejci38d85362019-09-05 16:26:38 +0200128 */
Radek Krejci1b2eef82021-02-17 11:17:27 +0100129void lysc_extension_instance_substatements_free(struct ly_ctx *ctx, struct lysc_ext_substmt *substmts);
Radek Krejci38d85362019-09-05 16:26:38 +0200130
131/**
Michal Vasko6f4cbb62020-02-28 11:15:47 +0100132 * @brief Duplicate the compiled extension (definition) structure.
Radek Krejci8678fa42020-08-18 16:07:28 +0200133 * TODO should this be in API? currently required by nacm_compile()
Michal Vasko6f4cbb62020-02-28 11:15:47 +0100134 * 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 Krejci1b2eef82021-02-17 11:17:27 +0100142 * @brief Get pointer to the storage of the specified substatement in the given extension instance.
143 *
144 * The function simplifies access into the ::lysc_ext_instance.substmts sized array.
145 *
146 * @param[in] ext Compiled extension instance to process.
147 * @param[in] substmt Extension substatement to search for.
148 * @param[out] instance_p Pointer where the storage of the @p substmt will be provided. The specific type returned depends
149 * on the @p substmt and can be found in the documentation of each ::ly_stmt value. Also note that some of the substatements
150 * (::lysc_node based or flags) can share the storage with other substatements. In case the pointer is NULL, still the return
151 * code can be used to at least know if the substatement is allowed for the extension.
152 * @param[out] cardinality_p Pointer to provide allowed cardinality of the substatements in the extension. Note that in some
153 * cases, the type of the storage depends also on the cardinality of the substatement.
154 * @return LY_SUCCESS if the @p substmt found.
155 * @return LY_ENOT in case the @p ext is not able to store (does not allow) the specified @p substmt.
156 */
157LY_ERR lysc_ext_substmt(const struct lysc_ext_instance *ext, enum ly_stmt substmt,
158 void **instance_p, enum ly_stmt_cardinality *cardinality_p);
159
Radek Krejcif16e2542021-02-17 15:39:23 +0100160const struct lysc_node *lys_find_ext_instance_node(const struct lysc_ext_instance *ext, const struct lys_module *module,
161 const char *name, size_t name_len, uint16_t nodetype, uint32_t options);
162
Radek Krejci1b2eef82021-02-17 11:17:27 +0100163/**
Radek Krejci0e59c312019-08-15 15:34:15 +0200164 * @brief Update path in the compile context, which is used for logging where the compilation failed.
165 *
166 * @param[in] ctx Compile context with the path.
Radek Krejci8678fa42020-08-18 16:07:28 +0200167 * @param[in] parent Parent of the current node to check difference with the currently processed module (taken from @p ctx).
Radek Krejci0e59c312019-08-15 15:34:15 +0200168 * @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
169 * call updates the segment to the form `{keyword='name'}` (to remove this compound segment, 2 calls with NULL @p name must be used).
170 */
171void lysc_update_path(struct lysc_ctx *ctx, struct lysc_node *parent, const char *name);
172
173/** @} extensionscompile */
174
175/**
176 * @brief Callback to compile extension from the lysp_ext_instance to the lysc_ext_instance. The later structure is generally prepared
177 * and only the extension specific data are supposed to be added (if any).
178 *
Radek Krejciadcf63d2021-02-09 10:21:18 +0100179 * The parsed generic statements can be processed by the callback on its own or the ::lys_compile_extension_instance
180 * function can be used to let the compilation to libyang following the standard rules for processing the YANG statements.
181 *
Radek Krejci0e59c312019-08-15 15:34:15 +0200182 * @param[in] cctx Current compile context.
183 * @param[in] p_ext Parsed extension instance data.
184 * @param[in,out] c_ext Prepared compiled extension instance structure where an addition, extension-specific, data are supposed to be placed
185 * for later use (data validation or use of external tool).
186 * @return LY_SUCCESS in case of success.
187 * @return LY_EVALID in case of non-conforming parsed data.
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100188 * @return LY_ENOT in case the extension instance is not supported and should be removed.
Radek Krejci0e59c312019-08-15 15:34:15 +0200189 */
190typedef LY_ERR (*lyext_clb_compile)(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext);
191
192/**
Radek Krejciadcf63d2021-02-09 10:21:18 +0100193 * @brief Callback to free the extension specific data created by the ::lyext_clb_compile callback of the same extension plugin.
Radek Krejci0e59c312019-08-15 15:34:15 +0200194 *
Radek Krejci38d85362019-09-05 16:26:38 +0200195 * @param[in] ctx libyang context.
Radek Krejci0e59c312019-08-15 15:34:15 +0200196 * @param[in,out] ext Compiled extension structure where the data to free are placed.
197 */
Radek Krejci38d85362019-09-05 16:26:38 +0200198typedef void (*lyext_clb_free)(struct ly_ctx *ctx, struct lysc_ext_instance *ext);
Radek Krejci0e59c312019-08-15 15:34:15 +0200199
200/**
201 * @brief Callback to decide if data instance is valid according to the schema.
202 *
203 * The callback is used only for the extension instances placed in the following parent statements
Radek Krejci8678fa42020-08-18 16:07:28 +0200204 * (which is specified as ::lysc_ext_instance.parent_type):
Radek Krejci0e59c312019-08-15 15:34:15 +0200205 * - LYEXT_PAR_NODE - @p node is instance of the schema node where the extension instance was specified.
206 * - 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.
207 * - LYEXT_PAR_TYPE - @p node is instance of the schema node with the value of the type where the extension instance was specified.
208 * - LYEXT_PAR_TYPE_BIT - @p node is instance of the schema node with the value of the bit where the extension instance was specified.
209 * - LYEXT_PAR_TYPE_ENUM - @p node is instance of the schema node with the value of the enum where the extension instance was specified.
210 *
211 * @param[in] ext Extension instance to be checked.
212 * @param[in] node Data node, where the extension data are supposed to be placed.
213 *
214 * @return LY_SUCCESS on data validation success.
215 * @return LY_EVALID in case the validation fails.
216 */
217typedef LY_ERR (*lyext_clb_data_validation)(struct lysc_ext_instance *ext, struct lyd_node *node);
218
219/**
Radek Krejciadcf63d2021-02-09 10:21:18 +0100220 * @brief Callback to print the compiled extension instance's private data in the INFO format.
221 *
222 * @param[in] ctx YANG printer context to provide output handler and other information for printing.
223 * @param[in] ext The compiled extension instance, mainly to access the extensions.
224 * @param[in, out] flag Flag to be shared with the caller regarding the opening brackets - 0 if the '{' not yet printed,
225 * 1 otherwise.
226 *
227 * @return LY_SUCCESS when everything was fine, other LY_ERR values in case of failure
228 */
229typedef LY_ERR (*lyext_clb_schema_printer)(struct lys_ypr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag);
230
231/**
Radek Krejci0e59c312019-08-15 15:34:15 +0200232 * @brief Extension plugin implementing various aspects of a YANG extension
233 */
234struct lyext_plugin {
235 const char *id; /**< Plugin identification (mainly for distinguish incompatible versions of the plugins for external tools) */
236 lyext_clb_compile compile; /**< Callback to compile extension instance from the parsed data */
237 lyext_clb_data_validation validate; /**< Callback to decide if data instance is valid according to the schema. */
Radek Krejciadcf63d2021-02-09 10:21:18 +0100238 lyext_clb_schema_printer sprinter; /**< Callback to print the compiled content (info format) of the extension instance */
239 /* lyext_clb_data_printer dprinter; ? */
Radek Krejci8678fa42020-08-18 16:07:28 +0200240 lyext_clb_free free; /**< Free the extension instance specific data created by ::lyext_plugin.compile callback */
Radek Krejci0e59c312019-08-15 15:34:15 +0200241};
242
Radek Krejci0935f412019-08-20 16:15:18 +0200243struct lyext_plugins_list {
244 const char *module; /**< name of the module where the extension is defined */
245 const char *revision; /**< optional module revision - if not specified, the plugin applies to any revision,
246 which is not an optimal approach due to a possible future revisions of the module.
247 Instead, there should be defined multiple items in the plugins list, each with the
248 different revision, but all with the same pointer to the plugin extension. The
249 only valid use case for the NULL revision is the case the module has no revision. */
250 const char *name; /**< name of the extension */
251 struct lyext_plugin *plugin; /**< plugin for the extension */
252};
253
Radek Krejci0935f412019-08-20 16:15:18 +0200254/**
255 * @brief Provide a log message from an extension plugin.
256 *
257 * @param[in] ext Compiled extension structure providing generic information about the extension/plugin causing the message.
258 * @param[in] level Log message level (error, warning, etc.)
259 * @param[in] err_no Error type code.
260 * @param[in] path Path relevant to the message.
261 * @param[in] format Format string to print.
262 */
263void lyext_log(const struct lysc_ext_instance *ext, LY_LOG_LEVEL level, LY_ERR err_no, const char *path, const char *format, ...);
264
Radek Krejci0e59c312019-08-15 15:34:15 +0200265/** @} extensions */
Radek Krejcid7e8a622018-10-29 15:54:55 +0100266
267#ifdef __cplusplus
268}
269#endif
270
Radek Krejci0935f412019-08-20 16:15:18 +0200271#endif /* LY_PLUGINS_EXTS_H_ */