diff options
Diffstat (limited to 'lib/yang.c')
| -rw-r--r-- | lib/yang.c | 121 |
1 files changed, 112 insertions, 9 deletions
diff --git a/lib/yang.c b/lib/yang.c index 013a762842..702fcf436d 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -11,6 +11,7 @@ #include "lib_errors.h" #include "yang.h" #include "yang_translator.h" +#include <libyang/version.h> #include "northbound.h" #include "frrstr.h" @@ -19,6 +20,17 @@ DEFINE_MTYPE_STATIC(LIB, YANG_MODULE, "YANG module"); DEFINE_MTYPE_STATIC(LIB, YANG_DATA, "YANG data structure"); +/* Safe to remove after libyang 2.2.8 */ +#if (LY_VERSION_MAJOR < 3) +#define yang_lyd_find_xpath3(ctx_node, tree, xpath, format, prefix_data, vars, \ + set) \ + lyd_find_xpath3(ctx_node, tree, xpath, vars, set) +#else +#define yang_lyd_find_xpath3(ctx_node, tree, xpath, format, prefix_data, vars, \ + set) \ + lyd_find_xpath3(ctx_node, tree, xpath, LY_VALUE_JSON, NULL, vars, set) +#endif + /* libyang container. */ struct ly_ctx *ly_native_ctx; @@ -653,6 +665,16 @@ void yang_dnode_free(struct lyd_node *dnode) lyd_free_all(dnode); } +void yang_dnode_rpc_output_add(struct lyd_node *output, const char *xpath, + const char *value) +{ + LY_ERR err; + + err = lyd_new_path(output, ly_native_ctx, xpath, value, + LYD_NEW_PATH_OUTPUT | LYD_NEW_PATH_UPDATE, NULL); + assert(err == LY_SUCCESS); +} + struct yang_data *yang_data_new(const char *xpath, const char *value) { struct yang_data *data; @@ -702,7 +724,12 @@ struct yang_data *yang_data_list_find(const struct list *list, } /* Make libyang log its errors using FRR logging infrastructure. */ -static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path) +static void ly_zlog_cb(LY_LOG_LEVEL level, const char *msg, const char *data_path +#if !(LY_VERSION_MAJOR < 3) + , + const char *schema_path, uint64_t line +#endif +) { int priority = LOG_ERR; @@ -719,8 +746,14 @@ static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path) break; } - if (path) - zlog(priority, "libyang: %s (%s)", msg, path); + if (data_path) + zlog(priority, "libyang: %s (%s)", msg, data_path); +#if !(LY_VERSION_MAJOR < 3) + else if (schema_path) + zlog(priority, "libyang %s (%s)\n", msg, schema_path); + else if (line) + zlog(priority, "libyang %s (line %" PRIu64 ")\n", msg, line); +#endif else zlog(priority, "libyang: %s", msg); } @@ -747,7 +780,8 @@ LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format, return err; } - err = lyd_find_xpath3(NULL, tree, xpath, NULL, &set); + err = yang_lyd_find_xpath3(NULL, tree, xpath, LY_VALUE_JSON, NULL, NULL, + &set); if (err) { zlog_err("Failed to parse notification: %s", ly_last_errmsg()); lyd_free_all(tree); @@ -764,6 +798,63 @@ LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format, return LY_SUCCESS; } +LY_ERR yang_parse_rpc(const char *xpath, LYD_FORMAT format, const char *data, + bool reply, struct lyd_node **rpc) +{ + const struct lysc_node *snode; + struct lyd_node *parent = NULL; + struct ly_in *in = NULL; + LY_ERR err; + + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); + if (!snode) { + zlog_err("Failed to find RPC/action schema node: %s", xpath); + return LY_ENOTFOUND; + } + + /* If it's an action, create its parent */ + if (snode->nodetype == LYS_ACTION) { + char *parent_xpath = XSTRDUP(MTYPE_TMP, xpath); + + if (yang_xpath_pop_node(parent_xpath) != NB_OK) { + XFREE(MTYPE_TMP, parent_xpath); + zlog_err("Invalid action xpath: %s", xpath); + return LY_EINVAL; + } + + err = lyd_new_path2(NULL, ly_native_ctx, parent_xpath, NULL, 0, + 0, 0, NULL, &parent); + XFREE(MTYPE_TMP, parent_xpath); + if (err) { + zlog_err("Failed to create parent node for action: %s", + ly_last_errmsg()); + return err; + } + } else if (snode->nodetype != LYS_RPC) { + zlog_err("Schema node is not an RPC/action: %s", xpath); + return LY_EINVAL; + } + + err = ly_in_new_memory(data, &in); + if (err) { + lyd_free_all(parent); + zlog_err("Failed to initialize ly_in: %s", ly_last_errmsg()); + return err; + } + + err = lyd_parse_op(ly_native_ctx, parent, in, format, + reply ? LYD_TYPE_REPLY_YANG : LYD_TYPE_RPC_YANG, + NULL, rpc); + ly_in_free(in, 0); + if (err) { + lyd_free_all(parent); + zlog_err("Failed to parse RPC/action: %s", ly_last_errmsg()); + return err; + } + + return LY_SUCCESS; +} + static ssize_t yang_print_darr(void *arg, const void *buf, size_t count) { uint8_t *dst = darr_append_n(*(uint8_t **)arg, count); @@ -840,23 +931,29 @@ char *yang_convert_lyd_format(const char *data, size_t data_len, const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, size_t buf_len) { - struct ly_err_item *ei; + const struct ly_err_item *ei; ei = ly_err_first(ly_ctx); if (!ei) return ""; strlcpy(buf, "YANG error(s):\n", buf_len); +#if (LY_VERSION_MAJOR < 3) +#define data_path path +#else +#define data_path data_path +#endif for (; ei; ei = ei->next) { - if (ei->path) { + if (ei->data_path) { strlcat(buf, " Path: ", buf_len); - strlcat(buf, ei->path, buf_len); + strlcat(buf, ei->data_path, buf_len); strlcat(buf, "\n", buf_len); } strlcat(buf, " Error: ", buf_len); strlcat(buf, ei->msg, buf_len); strlcat(buf, "\n", buf_len); } +#undef data_path ly_err_clean(ly_ctx, NULL); @@ -908,7 +1005,12 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile) void yang_init(bool embedded_modules, bool defer_compile) { /* Initialize libyang global parameters that affect all containers. */ - ly_set_log_clb(ly_log_cb, 1); + ly_set_log_clb(ly_zlog_cb +#if (LY_VERSION_MAJOR < 3) + , + 1 +#endif + ); ly_log_options(LY_LOLOG | LY_LOSTORE); /* Initialize libyang container for native models. */ @@ -1246,7 +1348,8 @@ LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath) *root = lyd_first_sibling(*root); - err = lyd_find_xpath3(NULL, *root, xpath, NULL, &set); + err = yang_lyd_find_xpath3(NULL, *root, xpath, LY_VALUE_JSON, NULL, + NULL, &set); if (err) { flog_err_sys(EC_LIB_LIBYANG, "cannot obtain specific result for xpath \"%s\": %s", |
