diff --git a/lib/hook.h b/lib/hook.h index 19e0f1fbfc..58aa2009b9 100644 --- a/lib/hook.h +++ b/lib/hook.h @@ -163,6 +163,8 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, _hook_unregister(&_hook_##hookname, \ _hook_typecheck_arg_##hookname(func), arg, true) +#define hook_have_hooks(hookname) (_hook_##hookname.entries != NULL) + /* invoke hooks * this is private (static) to the file that has the DEFINE_HOOK statement */ diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c index 286555c564..589bf82c95 100644 --- a/lib/mgmt_be_client.c +++ b/lib/mgmt_be_client.c @@ -311,13 +311,15 @@ static int be_client_send_error(struct mgmt_be_client *client, uint64_t txn_id, return ret; } -void mgmt_be_send_notification(struct lyd_node *tree) +static int mgmt_be_send_notification(void *__be_client, const char *xpath, + const struct lyd_node *tree) { struct mgmt_be_client *client = __be_client; struct mgmt_msg_notify_data *msg = NULL; LYD_FORMAT format = LYD_JSON; uint8_t **darrp; LY_ERR err; + int ret = 0; assert(tree); @@ -339,6 +341,7 @@ void mgmt_be_send_notification(struct lyd_node *tree) flog_err(EC_LIB_LIBYANG, "%s: error creating notification data: %s", __func__, ly_strerrcode(err)); + ret = 1; goto done; } @@ -346,53 +349,7 @@ void mgmt_be_send_notification(struct lyd_node *tree) mgmt_msg_native_get_msg_len(msg), false); done: mgmt_msg_native_free_msg(msg); - lyd_free_all(tree); -} - -/* - * Convert old style NB notification data into new MGMTD YANG tree and send. - */ -static int mgmt_be_notification_send(void *arg, const char *xpath, - struct list *args) -{ - struct lyd_node *root = NULL; - struct lyd_node *dnode; - struct yang_data *data; - struct listnode *ln; - LY_ERR err; - - debug_be_client("%s: sending notification: %s", __func__, xpath); - - /* - * Convert yang data args list to a libyang data tree - */ - for (ALL_LIST_ELEMENTS_RO(args, ln, data)) { - err = lyd_new_path(root, ly_native_ctx, data->xpath, - data->value, LYD_NEW_PATH_UPDATE, &dnode); - if (err != LY_SUCCESS) { -lyerr: - flog_err(EC_LIB_LIBYANG, - "%s: error creating notification data: %s", - __func__, ly_strerrcode(err)); - if (root) - lyd_free_all(root); - return 1; - } - if (!root) { - root = dnode; - while (root->parent) - root = lyd_parent(root); - } - } - - if (!root) { - err = lyd_new_path(NULL, ly_native_ctx, xpath, "", 0, &root); - if (err) - goto lyerr; - } - - mgmt_be_send_notification(root); - return 0; + return ret; } static int mgmt_be_send_txn_reply(struct mgmt_be_client *client_ctx, @@ -1202,7 +1159,7 @@ struct mgmt_be_client *mgmt_be_client_create(const char *client_name, "BE-client", debug_check_be_client()); /* Hook to receive notifications */ - hook_register_arg(nb_notification_send, mgmt_be_notification_send, + hook_register_arg(nb_notification_tree_send, mgmt_be_send_notification, client); debug_be_client("Initialized client '%s'", client_name); diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h index 361899fc1d..cd8b237526 100644 --- a/lib/mgmt_be_client.h +++ b/lib/mgmt_be_client.h @@ -143,15 +143,6 @@ extern int mgmt_be_send_subscr_req(struct mgmt_be_client *client_ctx, int n_config_xpaths, char **config_xpaths, int n_oper_xpaths, char **oper_xpaths); -/** - * mgmt_be_notification_send() - send a YANG notification to FE clients. - * @tree: libyang tree for the notification. The tree will be freed by - * this function. - * - */ -extern void mgmt_be_send_notification(struct lyd_node *tree); - - /* * Destroy backend client and cleanup everything. */ diff --git a/lib/northbound.c b/lib/northbound.c index d74773194c..a3d91e56af 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -2076,20 +2076,68 @@ DEFINE_HOOK(nb_notification_send, (const char *xpath, struct list *arguments), int nb_notification_send(const char *xpath, struct list *arguments) { + struct lyd_node *root = NULL; + struct lyd_node *dnode; + struct yang_data *data; + struct listnode *ln; + LY_ERR err; int ret; DEBUGD(&nb_dbg_notif, "northbound notification: %s", xpath); + /* + * Call old hook functions + */ ret = hook_call(nb_notification_send, xpath, arguments); + + if (!hook_have_hooks(nb_notification_tree_send)) + goto done; + /* + * Convert yang data arguments list to a libyang data tree for new hook + * functions. + */ + for (ALL_LIST_ELEMENTS_RO(arguments, ln, data)) { + err = lyd_new_path(root, ly_native_ctx, data->xpath, + data->value, LYD_NEW_PATH_UPDATE, &dnode); + if (err != LY_SUCCESS) + goto lyerr; + if (!root) { + root = dnode; + while (root->parent) + root = lyd_parent(root); + } + } + + if (!root) { + err = lyd_new_path(NULL, ly_native_ctx, xpath, "", 0, &root); + if (err) { +lyerr: + flog_err(EC_LIB_LIBYANG, + "%s: error creating notification data: %s", + __func__, ly_strerrcode(err)); + ret += 1; + goto done; + } + } + + /* + * Call new hook functions + */ + ret += nb_notification_tree_send(xpath, root); + +done: + if (root) + lyd_free_all(root); if (arguments) list_delete(&arguments); return ret; } -DEFINE_HOOK(nb_notification_tree_send, (struct lyd_node *tree), (tree)); +DEFINE_HOOK(nb_notification_tree_send, + (const char *xpath, const struct lyd_node *tree), (xpath, tree)); -int nb_notification_tree_send(struct lyd_node *tree) +int nb_notification_tree_send(const char *xpath, const struct lyd_node *tree) { int ret; @@ -2098,8 +2146,7 @@ int nb_notification_tree_send(struct lyd_node *tree) DEBUGD(&nb_dbg_notif, "northbound tree notification: %s", tree->schema->name); - ret = hook_call(nb_notification_tree_send, tree); - lyd_free_all(tree); + ret = hook_call(nb_notification_tree_send, xpath, tree); return ret; } diff --git a/lib/northbound.h b/lib/northbound.h index e9f2db9b6e..5be111cf0a 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -803,6 +803,8 @@ typedef enum nb_error (*nb_oper_data_finish_cb)(const struct lyd_node *tree, /* Hooks. */ DECLARE_HOOK(nb_notification_send, (const char *xpath, struct list *arguments), (xpath, arguments)); +DECLARE_HOOK(nb_notification_tree_send, + (const char *xpath, const struct lyd_node *tree), (xpath, tree)); DECLARE_HOOK(nb_client_debug_config_write, (struct vty *vty), (vty)); DECLARE_HOOK(nb_client_debug_set_all, (uint32_t flags, bool set), (flags, set)); @@ -1491,14 +1493,17 @@ extern int nb_notification_send(const char *xpath, struct list *arguments); * Send a YANG notification from a backend . This is a no-op unless th * 'nb_notification_tree_send' hook was registered by a northbound plugin. * + * xpath + * XPath of the YANG notification. + * * tree - * The libyang tree for the notification. The tree will be freed by - * this call. + * The libyang tree for the notification. * * Returns: * NB_OK on success, NB_ERR otherwise. */ -extern int nb_notification_tree_send(struct lyd_node *tree); +extern int nb_notification_tree_send(const char *xpath, + const struct lyd_node *tree); /* * Associate a user pointer to a configuration node.