lib: mgmt_be_client handles datastore notification using CBs

Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
Christian Hopps 2025-01-16 04:13:08 +00:00
parent 2375a11b08
commit 94f70c2100
3 changed files with 39 additions and 11 deletions

View file

@ -1114,19 +1114,24 @@ static void be_client_handle_notify(struct mgmt_be_client *client, void *msgbuf,
size_t msg_len) size_t msg_len)
{ {
struct mgmt_msg_notify_data *notif_msg = msgbuf; struct mgmt_msg_notify_data *notif_msg = msgbuf;
struct nb_node *nb_node; struct nb_node *nb_node, *nb_parent;
struct lyd_node *dnode; struct lyd_node *dnode = NULL;
const char *data = NULL; const char *data = NULL;
const char *notif; const char *notif;
LY_ERR err; bool is_yang_notify;
LY_ERR err = LY_SUCCESS;
debug_be_client("Received notification for client %s", client->name); debug_be_client("Received notification for client %s", client->name);
notif = mgmt_msg_native_xpath_data_decode(notif_msg, msg_len, data); notif = mgmt_msg_native_xpath_data_decode(notif_msg, msg_len, data);
if (!notif || !data) { if (!notif) {
log_err_be_client("Corrupt notify msg"); log_err_be_client("Corrupt notify msg");
return; return;
} }
if (!data && (notif_msg->op == NOTIFY_OP_DS_REPLACE || notif_msg->op == NOTIFY_OP_DS_PATCH)) {
log_err_be_client("Corrupt replace/patch notify msg: missing data");
return;
}
nb_node = nb_node_find(notif); nb_node = nb_node_find(notif);
if (!nb_node) { if (!nb_node) {
@ -1134,20 +1139,41 @@ static void be_client_handle_notify(struct mgmt_be_client *client, void *msgbuf,
return; return;
} }
if (!nb_node->cbs.notify) { is_yang_notify = !!CHECK_FLAG(nb_node->snode->nodetype, LYS_NOTIF);
if (is_yang_notify && !nb_node->cbs.notify) {
debug_be_client("No notification callback for: %s", notif); debug_be_client("No notification callback for: %s", notif);
return; return;
} }
err = yang_parse_notification(notif, notif_msg->result_type, data, if (!nb_node->cbs.notify) {
&dnode); /*
if (err) { * See if a parent has a callback, this is so backend's can
log_err_be_client("Can't parse notification data for: %s", * listen for changes on an entire datastore sub-tree.
*/
for (nb_parent = nb_node->parent; nb_parent; nb_parent = nb_node->parent)
if (nb_parent->cbs.notify)
break;
if (!nb_parent) {
debug_be_client("Including parents, no DS notification callback for: %s",
notif); notif);
return; return;
} }
nb_node = nb_parent;
}
nb_callback_notify(nb_node, notif, dnode); if (data && is_yang_notify) {
err = yang_parse_notification(notif, notif_msg->result_type, data, &dnode);
} else if (data) {
err = yang_parse_data(notif, notif_msg->result_type, false, true, false, data,
&dnode);
}
if (err) {
log_err_be_client("Can't parse notification data for: %s", notif);
return;
}
nb_callback_notify(nb_node, notif_msg->op, notif, dnode);
lyd_free_all(dnode); lyd_free_all(dnode);
} }

View file

@ -1857,7 +1857,7 @@ int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
return nb_node->cbs.rpc(&args); return nb_node->cbs.rpc(&args);
} }
void nb_callback_notify(const struct nb_node *nb_node, const char *xpath, void nb_callback_notify(const struct nb_node *nb_node, uint8_t op, const char *xpath,
struct lyd_node *dnode) struct lyd_node *dnode)
{ {
struct nb_cb_notify_args args = {}; struct nb_cb_notify_args args = {};
@ -1865,6 +1865,7 @@ void nb_callback_notify(const struct nb_node *nb_node, const char *xpath,
DEBUGD(&nb_dbg_cbs_notify, "northbound notify: %s", xpath); DEBUGD(&nb_dbg_cbs_notify, "northbound notify: %s", xpath);
args.xpath = xpath; args.xpath = xpath;
args.op = op;
args.dnode = dnode; args.dnode = dnode;
nb_node->cbs.notify(&args); nb_node->cbs.notify(&args);
} }

View file

@ -305,6 +305,7 @@ struct nb_cb_rpc_args {
struct nb_cb_notify_args { struct nb_cb_notify_args {
/* XPath of the notification. */ /* XPath of the notification. */
const char *xpath; const char *xpath;
uint8_t op;
/* /*
* libyang data node representing the notification. If the notification * libyang data node representing the notification. If the notification
@ -861,7 +862,7 @@ extern const void *nb_callback_lookup_next(const struct nb_node *nb_node,
extern int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath, extern int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
const struct lyd_node *input, struct lyd_node *output, const struct lyd_node *input, struct lyd_node *output,
char *errmsg, size_t errmsg_len); char *errmsg, size_t errmsg_len);
extern void nb_callback_notify(const struct nb_node *nb_node, const char *xpath, extern void nb_callback_notify(const struct nb_node *nb_node, uint8_t op, const char *xpath,
struct lyd_node *dnode); struct lyd_node *dnode);
/* /*