|
From 97cd849362b45ecbcb20194b5771c5ce777de6bc Mon Sep 17 00:00:00 2001
|
|
From: Renato Westphal <renato@opensourcerouting.org>
|
|
Date: Tue, 21 Apr 2020 21:27:47 -0300
|
|
Subject: [PATCH] lib: create a wrapper function for all northbound callbacks
|
|
|
|
The intention here is to keep the code more organized. These wrappers
|
|
should be used by the northbound clients only, and never directly
|
|
by any YANG backend code.
|
|
|
|
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
|
|
---
|
|
lib/northbound.c | 222 +++++++++++++++++++++++-----------------
|
|
lib/northbound_grpc.cpp | 3 +-
|
|
2 files changed, 131 insertions(+), 94 deletions(-)
|
|
|
|
diff --git a/lib/northbound.c b/lib/northbound.c
|
|
index 85e723d7cf..d10e4713f5 100644
|
|
--- a/lib/northbound.c
|
|
+++ b/lib/northbound.c
|
|
@@ -62,11 +62,10 @@ static struct {
|
|
*/
|
|
static bool transaction_in_progress;
|
|
|
|
+static int nb_callback_pre_validate(const struct nb_node *nb_node,
|
|
+ const struct lyd_node *dnode);
|
|
static int nb_callback_configuration(const enum nb_event event,
|
|
struct nb_config_change *change);
|
|
-static void nb_log_callback(const enum nb_event event,
|
|
- enum nb_operation operation, const char *xpath,
|
|
- const char *value);
|
|
static struct nb_transaction *nb_transaction_new(struct nb_config *config,
|
|
struct nb_config_cbs *changes,
|
|
enum nb_client client,
|
|
@@ -609,18 +608,7 @@ static int nb_candidate_validate_code(struct nb_config *candidate,
|
|
if (!nb_node->cbs.pre_validate)
|
|
goto next;
|
|
|
|
- if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config,
|
|
- DEBUG_MODE_ALL)) {
|
|
- char xpath[XPATH_MAXLEN];
|
|
-
|
|
- yang_dnode_get_path(child, xpath,
|
|
- sizeof(xpath));
|
|
- nb_log_callback(NB_EV_VALIDATE,
|
|
- NB_OP_PRE_VALIDATE, xpath,
|
|
- NULL);
|
|
- }
|
|
-
|
|
- ret = (*nb_node->cbs.pre_validate)(child);
|
|
+ ret = nb_callback_pre_validate(nb_node, child);
|
|
if (ret != NB_OK)
|
|
return NB_ERR_VALIDATION;
|
|
|
|
@@ -791,14 +779,128 @@ int nb_running_lock_check(enum nb_client client, const void *user)
|
|
return ret;
|
|
}
|
|
|
|
-static void nb_log_callback(const enum nb_event event,
|
|
- enum nb_operation operation, const char *xpath,
|
|
- const char *value)
|
|
+static void nb_log_config_callback(const enum nb_event event,
|
|
+ enum nb_operation operation,
|
|
+ const struct lyd_node *dnode)
|
|
{
|
|
+ const char *value;
|
|
+ char xpath[XPATH_MAXLEN];
|
|
+
|
|
+ if (!DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL))
|
|
+ return;
|
|
+
|
|
+ yang_dnode_get_path(dnode, xpath, sizeof(xpath));
|
|
+ if (yang_snode_is_typeless_data(dnode->schema))
|
|
+ value = "(none)";
|
|
+ else
|
|
+ value = yang_dnode_get_string(dnode, NULL);
|
|
+
|
|
zlog_debug(
|
|
"northbound callback: event [%s] op [%s] xpath [%s] value [%s]",
|
|
nb_event_name(event), nb_operation_name(operation), xpath,
|
|
- value ? value : "(NULL)");
|
|
+ value);
|
|
+}
|
|
+
|
|
+static int nb_callback_create(const struct nb_node *nb_node,
|
|
+ enum nb_event event, const struct lyd_node *dnode,
|
|
+ union nb_resource *resource)
|
|
+{
|
|
+ nb_log_config_callback(event, NB_OP_CREATE, dnode);
|
|
+
|
|
+ return nb_node->cbs.create(event, dnode, resource);
|
|
+}
|
|
+
|
|
+static int nb_callback_modify(const struct nb_node *nb_node,
|
|
+ enum nb_event event, const struct lyd_node *dnode,
|
|
+ union nb_resource *resource)
|
|
+{
|
|
+ nb_log_config_callback(event, NB_OP_MODIFY, dnode);
|
|
+
|
|
+ return nb_node->cbs.modify(event, dnode, resource);
|
|
+}
|
|
+
|
|
+static int nb_callback_destroy(const struct nb_node *nb_node,
|
|
+ enum nb_event event,
|
|
+ const struct lyd_node *dnode)
|
|
+{
|
|
+ nb_log_config_callback(event, NB_OP_DESTROY, dnode);
|
|
+
|
|
+ return nb_node->cbs.destroy(event, dnode);
|
|
+}
|
|
+
|
|
+static int nb_callback_move(const struct nb_node *nb_node, enum nb_event event,
|
|
+ const struct lyd_node *dnode)
|
|
+{
|
|
+ nb_log_config_callback(event, NB_OP_MOVE, dnode);
|
|
+
|
|
+ return nb_node->cbs.move(event, dnode);
|
|
+}
|
|
+
|
|
+static int nb_callback_pre_validate(const struct nb_node *nb_node,
|
|
+ const struct lyd_node *dnode)
|
|
+{
|
|
+ nb_log_config_callback(NB_EV_VALIDATE, NB_OP_PRE_VALIDATE, dnode);
|
|
+
|
|
+ return nb_node->cbs.pre_validate(dnode);
|
|
+}
|
|
+
|
|
+static void nb_callback_apply_finish(const struct nb_node *nb_node,
|
|
+ const struct lyd_node *dnode)
|
|
+{
|
|
+ nb_log_config_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH, dnode);
|
|
+
|
|
+ nb_node->cbs.apply_finish(dnode);
|
|
+}
|
|
+
|
|
+struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node,
|
|
+ const char *xpath,
|
|
+ const void *list_entry)
|
|
+{
|
|
+ DEBUGD(&nb_dbg_cbs_state,
|
|
+ "northbound callback (get_elem): xpath [%s] list_entry [%p]",
|
|
+ xpath, list_entry);
|
|
+
|
|
+ return nb_node->cbs.get_elem(xpath, list_entry);
|
|
+}
|
|
+
|
|
+const void *nb_callback_get_next(const struct nb_node *nb_node,
|
|
+ const void *parent_list_entry,
|
|
+ const void *list_entry)
|
|
+{
|
|
+ DEBUGD(&nb_dbg_cbs_state,
|
|
+ "northbound callback (get_next): node [%s] parent_list_entry [%p] list_entry [%p]",
|
|
+ nb_node->xpath, parent_list_entry, list_entry);
|
|
+
|
|
+ return nb_node->cbs.get_next(parent_list_entry, list_entry);
|
|
+}
|
|
+
|
|
+int nb_callback_get_keys(const struct nb_node *nb_node, const void *list_entry,
|
|
+ struct yang_list_keys *keys)
|
|
+{
|
|
+ DEBUGD(&nb_dbg_cbs_state,
|
|
+ "northbound callback (get_keys): node [%s] list_entry [%p]",
|
|
+ nb_node->xpath, list_entry);
|
|
+
|
|
+ return nb_node->cbs.get_keys(list_entry, keys);
|
|
+}
|
|
+
|
|
+const void *nb_callback_lookup_entry(const struct nb_node *nb_node,
|
|
+ const void *parent_list_entry,
|
|
+ const struct yang_list_keys *keys)
|
|
+{
|
|
+ DEBUGD(&nb_dbg_cbs_state,
|
|
+ "northbound callback (lookup_entry): node [%s] parent_list_entry [%p]",
|
|
+ nb_node->xpath, parent_list_entry);
|
|
+
|
|
+ return nb_node->cbs.lookup_entry(parent_list_entry, keys);
|
|
+}
|
|
+
|
|
+int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
|
|
+ const struct list *input, struct list *output)
|
|
+{
|
|
+ DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath);
|
|
+
|
|
+ return nb_node->cbs.rpc(xpath, input, output);
|
|
}
|
|
|
|
/*
|
|
@@ -815,15 +917,6 @@ static int nb_callback_configuration(const enum nb_event event,
|
|
union nb_resource *resource;
|
|
int ret = NB_ERR;
|
|
|
|
- if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) {
|
|
- const char *value = "(none)";
|
|
-
|
|
- if (dnode && !yang_snode_is_typeless_data(dnode->schema))
|
|
- value = yang_dnode_get_string(dnode, NULL);
|
|
-
|
|
- yang_dnode_get_path(dnode, xpath, sizeof(xpath));
|
|
- nb_log_callback(event, operation, xpath, value);
|
|
- }
|
|
|
|
if (event == NB_EV_VALIDATE)
|
|
resource = NULL;
|
|
@@ -832,16 +925,16 @@ static int nb_callback_configuration(const enum nb_event event,
|
|
|
|
switch (operation) {
|
|
case NB_OP_CREATE:
|
|
- ret = (*nb_node->cbs.create)(event, dnode, resource);
|
|
+ ret = nb_callback_create(nb_node, event, dnode, resource);
|
|
break;
|
|
case NB_OP_MODIFY:
|
|
- ret = (*nb_node->cbs.modify)(event, dnode, resource);
|
|
+ ret = nb_callback_modify(nb_node, event, dnode, resource);
|
|
break;
|
|
case NB_OP_DESTROY:
|
|
- ret = (*nb_node->cbs.destroy)(event, dnode);
|
|
+ ret = nb_callback_destroy(nb_node, event, dnode);
|
|
break;
|
|
case NB_OP_MOVE:
|
|
- ret = (*nb_node->cbs.move)(event, dnode);
|
|
+ ret = nb_callback_move(nb_node, event, dnode);
|
|
break;
|
|
default:
|
|
yang_dnode_get_path(dnode, xpath, sizeof(xpath));
|
|
@@ -890,57 +983,6 @@ static int nb_callback_configuration(const enum nb_event event,
|
|
return ret;
|
|
}
|
|
|
|
-struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node,
|
|
- const char *xpath,
|
|
- const void *list_entry)
|
|
-{
|
|
- DEBUGD(&nb_dbg_cbs_state,
|
|
- "northbound callback (get_elem): xpath [%s] list_entry [%p]",
|
|
- xpath, list_entry);
|
|
-
|
|
- return nb_node->cbs.get_elem(xpath, list_entry);
|
|
-}
|
|
-
|
|
-const void *nb_callback_get_next(const struct nb_node *nb_node,
|
|
- const void *parent_list_entry,
|
|
- const void *list_entry)
|
|
-{
|
|
- DEBUGD(&nb_dbg_cbs_state,
|
|
- "northbound callback (get_next): node [%s] parent_list_entry [%p] list_entry [%p]",
|
|
- nb_node->xpath, parent_list_entry, list_entry);
|
|
-
|
|
- return nb_node->cbs.get_next(parent_list_entry, list_entry);
|
|
-}
|
|
-
|
|
-int nb_callback_get_keys(const struct nb_node *nb_node, const void *list_entry,
|
|
- struct yang_list_keys *keys)
|
|
-{
|
|
- DEBUGD(&nb_dbg_cbs_state,
|
|
- "northbound callback (get_keys): node [%s] list_entry [%p]",
|
|
- nb_node->xpath, list_entry);
|
|
-
|
|
- return nb_node->cbs.get_keys(list_entry, keys);
|
|
-}
|
|
-
|
|
-const void *nb_callback_lookup_entry(const struct nb_node *nb_node,
|
|
- const void *parent_list_entry,
|
|
- const struct yang_list_keys *keys)
|
|
-{
|
|
- DEBUGD(&nb_dbg_cbs_state,
|
|
- "northbound callback (lookup_entry): node [%s] parent_list_entry [%p]",
|
|
- nb_node->xpath, parent_list_entry);
|
|
-
|
|
- return nb_node->cbs.lookup_entry(parent_list_entry, keys);
|
|
-}
|
|
-
|
|
-int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
|
|
- const struct list *input, struct list *output)
|
|
-{
|
|
- DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath);
|
|
-
|
|
- return nb_node->cbs.rpc(xpath, input, output);
|
|
-}
|
|
-
|
|
static struct nb_transaction *
|
|
nb_transaction_new(struct nb_config *config, struct nb_config_cbs *changes,
|
|
enum nb_client client, const void *user, const char *comment)
|
|
@@ -1058,7 +1100,6 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction)
|
|
{
|
|
struct nb_config_cbs cbs;
|
|
struct nb_config_cb *cb;
|
|
- char xpath[XPATH_MAXLEN];
|
|
|
|
/* Initialize tree of 'apply_finish' callbacks. */
|
|
RB_INIT(nb_config_cbs, &cbs);
|
|
@@ -1075,6 +1116,8 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction)
|
|
* be called though).
|
|
*/
|
|
if (change->cb.operation == NB_OP_DESTROY) {
|
|
+ char xpath[XPATH_MAXLEN];
|
|
+
|
|
dnode = dnode->parent;
|
|
if (!dnode)
|
|
break;
|
|
@@ -1111,15 +1154,8 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction)
|
|
}
|
|
|
|
/* Call the 'apply_finish' callbacks, sorted by their priorities. */
|
|
- RB_FOREACH (cb, nb_config_cbs, &cbs) {
|
|
- if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) {
|
|
- yang_dnode_get_path(cb->dnode, xpath, sizeof(xpath));
|
|
- nb_log_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH, xpath,
|
|
- NULL);
|
|
- }
|
|
-
|
|
- (*cb->nb_node->cbs.apply_finish)(cb->dnode);
|
|
- }
|
|
+ RB_FOREACH (cb, nb_config_cbs, &cbs)
|
|
+ nb_callback_apply_finish(cb->nb_node, cb->dnode);
|
|
|
|
/* Release memory. */
|
|
while (!RB_EMPTY(nb_config_cbs, &cbs)) {
|
|
diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp
|
|
index b195f1aeca..66bf05c1ab 100644
|
|
--- a/lib/northbound_grpc.cpp
|
|
+++ b/lib/northbound_grpc.cpp
|
|
@@ -545,7 +545,8 @@ class NorthboundImpl final : public frr::Northbound::Service
|
|
}
|
|
|
|
// Execute callback registered for this XPath.
|
|
- if (nb_node->cbs.rpc(xpath, input_list, output_list) != NB_OK) {
|
|
+ if (nb_callback_rpc(nb_node, xpath, input_list, output_list)
|
|
+ != NB_OK) {
|
|
flog_warn(EC_LIB_NB_CB_RPC,
|
|
"%s: rpc callback failed: %s", __func__,
|
|
xpath);
|