diff options
-rw-r--r-- | lib/libfrr.c | 8 | ||||
-rw-r--r-- | lib/northbound.c | 93 | ||||
-rw-r--r-- | lib/northbound.h | 75 | ||||
-rw-r--r-- | lib/northbound_cli.c | 32 | ||||
-rw-r--r-- | lib/northbound_confd.c | 6 | ||||
-rw-r--r-- | lib/northbound_db.c | 2 | ||||
-rw-r--r-- | lib/northbound_grpc.cpp | 12 | ||||
-rw-r--r-- | lib/northbound_sysrepo.c | 10 | ||||
-rw-r--r-- | lib/vty.c | 9 |
9 files changed, 168 insertions, 79 deletions
diff --git a/lib/libfrr.c b/lib/libfrr.c index ac165f254..d52cef3fe 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -902,11 +902,13 @@ static int frr_config_read_in(struct thread *t) * reading the configuration file. */ if (frr_get_cli_mode() == FRR_CLI_TRANSACTIONAL) { + struct nb_context context = {}; int ret; - ret = nb_candidate_commit(vty_shared_candidate_config, - NB_CLIENT_CLI, NULL, true, - "Read configuration file", NULL); + context.client = NB_CLIENT_CLI; + ret = nb_candidate_commit(&context, vty_shared_candidate_config, + true, "Read configuration file", + NULL); if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) zlog_err("%s: failed to read configuration file.", __func__); diff --git a/lib/northbound.c b/lib/northbound.c index c49aff70b..e5349ad4e 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -62,14 +62,15 @@ static struct { */ static bool transaction_in_progress; -static int nb_callback_pre_validate(const struct nb_node *nb_node, +static int nb_callback_pre_validate(struct nb_context *context, + const struct nb_node *nb_node, const struct lyd_node *dnode); -static int nb_callback_configuration(const enum nb_event event, +static int nb_callback_configuration(struct nb_context *context, + const enum nb_event event, struct nb_config_change *change); -static struct nb_transaction *nb_transaction_new(struct nb_config *config, +static struct nb_transaction *nb_transaction_new(struct nb_context *context, + struct nb_config *config, struct nb_config_cbs *changes, - enum nb_client client, - const void *user, const char *comment); static void nb_transaction_free(struct nb_transaction *transaction); static int nb_transaction_process(enum nb_event event, @@ -592,7 +593,8 @@ static int nb_candidate_validate_yang(struct nb_config *candidate) } /* Perform code-level validation using the northbound callbacks. */ -static int nb_candidate_validate_code(struct nb_config *candidate, +static int nb_candidate_validate_code(struct nb_context *context, + struct nb_config *candidate, struct nb_config_cbs *changes) { struct nb_config_cb *cb; @@ -608,7 +610,7 @@ static int nb_candidate_validate_code(struct nb_config *candidate, if (!nb_node->cbs.pre_validate) goto next; - ret = nb_callback_pre_validate(nb_node, child); + ret = nb_callback_pre_validate(context, nb_node, child); if (ret != NB_OK) return NB_ERR_VALIDATION; @@ -621,7 +623,8 @@ static int nb_candidate_validate_code(struct nb_config *candidate, RB_FOREACH (cb, nb_config_cbs, changes) { struct nb_config_change *change = (struct nb_config_change *)cb; - ret = nb_callback_configuration(NB_EV_VALIDATE, change); + ret = nb_callback_configuration(context, NB_EV_VALIDATE, + change); if (ret != NB_OK) return NB_ERR_VALIDATION; } @@ -629,7 +632,8 @@ static int nb_candidate_validate_code(struct nb_config *candidate, return NB_OK; } -int nb_candidate_validate(struct nb_config *candidate) +int nb_candidate_validate(struct nb_context *context, + struct nb_config *candidate) { struct nb_config_cbs changes; int ret; @@ -639,14 +643,14 @@ int nb_candidate_validate(struct nb_config *candidate) RB_INIT(nb_config_cbs, &changes); nb_config_diff(running_config, candidate, &changes); - ret = nb_candidate_validate_code(candidate, &changes); + ret = nb_candidate_validate_code(context, candidate, &changes); nb_config_diff_del_changes(&changes); return ret; } -int nb_candidate_commit_prepare(struct nb_config *candidate, - enum nb_client client, const void *user, +int nb_candidate_commit_prepare(struct nb_context *context, + struct nb_config *candidate, const char *comment, struct nb_transaction **transaction) { @@ -664,7 +668,7 @@ int nb_candidate_commit_prepare(struct nb_config *candidate, if (RB_EMPTY(nb_config_cbs, &changes)) return NB_ERR_NO_CHANGES; - if (nb_candidate_validate_code(candidate, &changes) != NB_OK) { + if (nb_candidate_validate_code(context, candidate, &changes) != NB_OK) { flog_warn(EC_LIB_NB_CANDIDATE_INVALID, "%s: failed to validate candidate configuration", __func__); @@ -673,7 +677,7 @@ int nb_candidate_commit_prepare(struct nb_config *candidate, } *transaction = - nb_transaction_new(candidate, &changes, client, user, comment); + nb_transaction_new(context, candidate, &changes, comment); if (*transaction == NULL) { flog_warn(EC_LIB_NB_TRANSACTION_CREATION_FAILED, "%s: failed to create transaction", __func__); @@ -709,14 +713,14 @@ void nb_candidate_commit_apply(struct nb_transaction *transaction, nb_transaction_free(transaction); } -int nb_candidate_commit(struct nb_config *candidate, enum nb_client client, - const void *user, bool save_transaction, - const char *comment, uint32_t *transaction_id) +int nb_candidate_commit(struct nb_context *context, struct nb_config *candidate, + bool save_transaction, const char *comment, + uint32_t *transaction_id) { struct nb_transaction *transaction = NULL; int ret; - ret = nb_candidate_commit_prepare(candidate, client, user, comment, + ret = nb_candidate_commit_prepare(context, candidate, comment, &transaction); /* * Apply the changes if the preparation phase succeeded. Otherwise abort @@ -801,7 +805,8 @@ static void nb_log_config_callback(const enum nb_event event, value); } -static int nb_callback_create(const struct nb_node *nb_node, +static int nb_callback_create(struct nb_context *context, + const struct nb_node *nb_node, enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { @@ -809,13 +814,15 @@ static int nb_callback_create(const struct nb_node *nb_node, nb_log_config_callback(event, NB_OP_CREATE, dnode); + args.context = context; args.event = event; args.dnode = dnode; args.resource = resource; return nb_node->cbs.create(&args); } -static int nb_callback_modify(const struct nb_node *nb_node, +static int nb_callback_modify(struct nb_context *context, + const struct nb_node *nb_node, enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { @@ -823,13 +830,15 @@ static int nb_callback_modify(const struct nb_node *nb_node, nb_log_config_callback(event, NB_OP_MODIFY, dnode); + args.context = context; args.event = event; args.dnode = dnode; args.resource = resource; return nb_node->cbs.modify(&args); } -static int nb_callback_destroy(const struct nb_node *nb_node, +static int nb_callback_destroy(struct nb_context *context, + const struct nb_node *nb_node, enum nb_event event, const struct lyd_node *dnode) { @@ -837,24 +846,28 @@ static int nb_callback_destroy(const struct nb_node *nb_node, nb_log_config_callback(event, NB_OP_DESTROY, dnode); + args.context = context; args.event = event; args.dnode = dnode; return nb_node->cbs.destroy(&args); } -static int nb_callback_move(const struct nb_node *nb_node, enum nb_event event, +static int nb_callback_move(struct nb_context *context, + const struct nb_node *nb_node, enum nb_event event, const struct lyd_node *dnode) { struct nb_cb_move_args args = {}; nb_log_config_callback(event, NB_OP_MOVE, dnode); + args.context = context; args.event = event; args.dnode = dnode; return nb_node->cbs.move(&args); } -static int nb_callback_pre_validate(const struct nb_node *nb_node, +static int nb_callback_pre_validate(struct nb_context *context, + const struct nb_node *nb_node, const struct lyd_node *dnode) { struct nb_cb_pre_validate_args args = {}; @@ -865,13 +878,15 @@ static int nb_callback_pre_validate(const struct nb_node *nb_node, return nb_node->cbs.pre_validate(&args); } -static void nb_callback_apply_finish(const struct nb_node *nb_node, +static void nb_callback_apply_finish(struct nb_context *context, + const struct nb_node *nb_node, const struct lyd_node *dnode) { struct nb_cb_apply_finish_args args = {}; nb_log_config_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH, dnode); + args.context = context; args.dnode = dnode; nb_node->cbs.apply_finish(&args); } @@ -952,7 +967,8 @@ int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath, * Call the northbound configuration callback associated to a given * configuration change. */ -static int nb_callback_configuration(const enum nb_event event, +static int nb_callback_configuration(struct nb_context *context, + const enum nb_event event, struct nb_config_change *change) { enum nb_operation operation = change->cb.operation; @@ -969,16 +985,18 @@ static int nb_callback_configuration(const enum nb_event event, switch (operation) { case NB_OP_CREATE: - ret = nb_callback_create(nb_node, event, dnode, resource); + ret = nb_callback_create(context, nb_node, event, dnode, + resource); break; case NB_OP_MODIFY: - ret = nb_callback_modify(nb_node, event, dnode, resource); + ret = nb_callback_modify(context, nb_node, event, dnode, + resource); break; case NB_OP_DESTROY: - ret = nb_callback_destroy(nb_node, event, dnode); + ret = nb_callback_destroy(context, nb_node, event, dnode); break; case NB_OP_MOVE: - ret = nb_callback_move(nb_node, event, dnode); + ret = nb_callback_move(context, nb_node, event, dnode); break; default: yang_dnode_get_path(dnode, xpath, sizeof(xpath)); @@ -1027,13 +1045,14 @@ static int nb_callback_configuration(const enum nb_event event, return ret; } -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) +static struct nb_transaction *nb_transaction_new(struct nb_context *context, + struct nb_config *config, + struct nb_config_cbs *changes, + const char *comment) { struct nb_transaction *transaction; - if (nb_running_lock_check(client, user)) { + if (nb_running_lock_check(context->client, context->user)) { flog_warn( EC_LIB_NB_TRANSACTION_CREATION_FAILED, "%s: running configuration is locked by another client", @@ -1051,7 +1070,7 @@ nb_transaction_new(struct nb_config *config, struct nb_config_cbs *changes, transaction_in_progress = true; transaction = XCALLOC(MTYPE_TMP, sizeof(*transaction)); - transaction->client = client; + transaction->context = context; if (comment) strlcpy(transaction->comment, comment, sizeof(transaction->comment)); @@ -1086,7 +1105,8 @@ static int nb_transaction_process(enum nb_event event, break; /* Call the appropriate callback. */ - ret = nb_callback_configuration(event, change); + ret = nb_callback_configuration(transaction->context, event, + change); switch (event) { case NB_EV_PREPARE: if (ret != NB_OK) @@ -1199,7 +1219,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) - nb_callback_apply_finish(cb->nb_node, cb->dnode); + nb_callback_apply_finish(transaction->context, cb->nb_node, + cb->dnode); /* Release memory. */ while (!RB_EMPTY(nb_config_cbs, &cbs)) { diff --git a/lib/northbound.h b/lib/northbound.h index 44727ca0d..caa7a9f82 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -91,6 +91,9 @@ union nb_resource { */ struct nb_cb_create_args { + /* Context of the configuration transaction. */ + struct nb_context *context; + /* * The transaction phase. Refer to the documentation comments of * nb_event for more details. @@ -110,6 +113,9 @@ struct nb_cb_create_args { }; struct nb_cb_modify_args { + /* Context of the configuration transaction. */ + struct nb_context *context; + /* * The transaction phase. Refer to the documentation comments of * nb_event for more details. @@ -129,6 +135,9 @@ struct nb_cb_modify_args { }; struct nb_cb_destroy_args { + /* Context of the configuration transaction. */ + struct nb_context *context; + /* * The transaction phase. Refer to the documentation comments of * nb_event for more details. @@ -140,6 +149,9 @@ struct nb_cb_destroy_args { }; struct nb_cb_move_args { + /* Context of the configuration transaction. */ + struct nb_context *context; + /* * The transaction phase. Refer to the documentation comments of * nb_event for more details. @@ -151,11 +163,17 @@ struct nb_cb_move_args { }; struct nb_cb_pre_validate_args { + /* Context of the configuration transaction. */ + struct nb_context *context; + /* libyang data node associated with the 'pre_validate' callback. */ const struct lyd_node *dnode; }; struct nb_cb_apply_finish_args { + /* Context of the configuration transaction. */ + struct nb_context *context; + /* libyang data node associated with the 'apply_finish' callback. */ const struct lyd_node *dnode; }; @@ -538,6 +556,29 @@ enum nb_client { NB_CLIENT_GRPC, }; +/* Northbound context. */ +struct nb_context { + /* Northbound client. */ + enum nb_client client; + + /* Northbound user (can be NULL). */ + const void *user; + + /* Client-specific data. */ +#if 0 + union { + struct { + } cli; + struct { + } confd; + struct { + } sysrepo; + struct { + } grpc; + } client_data; +#endif +}; + /* Northbound configuration. */ struct nb_config { struct lyd_node *dnode; @@ -564,7 +605,7 @@ struct nb_config_change { /* Northbound configuration transaction. */ struct nb_transaction { - enum nb_client client; + struct nb_context *context; char comment[80]; struct nb_config *config; struct nb_config_cbs changes; @@ -762,28 +803,29 @@ extern int nb_candidate_update(struct nb_config *candidate); * WARNING: the candidate can be modified as part of the validation process * (e.g. add default nodes). * + * context + * Context of the northbound transaction. + * * candidate * Candidate configuration to validate. * * Returns: * NB_OK on success, NB_ERR_VALIDATION otherwise. */ -extern int nb_candidate_validate(struct nb_config *candidate); +extern int nb_candidate_validate(struct nb_context *context, + struct nb_config *candidate); /* * Create a new configuration transaction but do not commit it yet. Only * validate the candidate and prepare all resources required to apply the * configuration changes. * + * context + * Context of the northbound transaction. + * * candidate * Candidate configuration to commit. * - * client - * Northbound client performing the commit. - * - * user - * Northbound user performing the commit (can be NULL). - * * comment * Optional comment describing the commit. * @@ -803,8 +845,8 @@ extern int nb_candidate_validate(struct nb_config *candidate); * the candidate configuration. * - NB_ERR for other errors. */ -extern int nb_candidate_commit_prepare(struct nb_config *candidate, - enum nb_client client, const void *user, +extern int nb_candidate_commit_prepare(struct nb_context *context, + struct nb_config *candidate, const char *comment, struct nb_transaction **transaction); @@ -842,16 +884,13 @@ extern void nb_candidate_commit_apply(struct nb_transaction *transaction, * take into account the results of the preparation phase of multiple managed * entities. * + * context + * Context of the northbound transaction. + * * candidate * Candidate configuration to commit. It's preserved regardless if the commit * operation fails or not. * - * client - * Northbound client performing the commit. - * - * user - * Northbound user performing the commit (can be NULL). - * * save_transaction * Specify whether the transaction should be recorded in the transactions log * or not. @@ -872,8 +911,8 @@ extern void nb_candidate_commit_apply(struct nb_transaction *transaction, * the candidate configuration. * - NB_ERR for other errors. */ -extern int nb_candidate_commit(struct nb_config *candidate, - enum nb_client client, const void *user, +extern int nb_candidate_commit(struct nb_context *context, + struct nb_config *candidate, bool save_transaction, const char *comment, uint32_t *transaction_id); diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index d4467faca..544b2434e 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -169,8 +169,12 @@ int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...) /* Do an implicit "commit" when using the classic CLI mode. */ if (frr_get_cli_mode() == FRR_CLI_CLASSIC) { - ret = nb_candidate_commit(vty->candidate_config, NB_CLIENT_CLI, - vty, false, NULL, NULL); + struct nb_context context = {}; + + context.client = NB_CLIENT_CLI; + context.user = vty; + ret = nb_candidate_commit(&context, vty->candidate_config, + false, NULL, NULL); if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) { vty_out(vty, "%% Configuration failed: %s.\n\n", nb_err_name(ret)); @@ -217,12 +221,16 @@ void nb_cli_confirmed_commit_clean(struct vty *vty) int nb_cli_confirmed_commit_rollback(struct vty *vty) { + struct nb_context context = {}; uint32_t transaction_id; int ret; + /* Perform the rollback. */ + context.client = NB_CLIENT_CLI; + context.user = vty; ret = nb_candidate_commit( - vty->confirmed_commit_rollback, NB_CLIENT_CLI, vty, true, + &context, vty->confirmed_commit_rollback, true, "Rollback to previous configuration - confirmed commit has timed out", &transaction_id); if (ret == NB_OK) @@ -252,6 +260,7 @@ static int nb_cli_confirmed_commit_timeout(struct thread *thread) static int nb_cli_commit(struct vty *vty, bool force, unsigned int confirmed_timeout, char *comment) { + struct nb_context context = {}; uint32_t transaction_id = 0; int ret; @@ -295,8 +304,10 @@ static int nb_cli_commit(struct vty *vty, bool force, &vty->t_confirmed_commit_timeout); } - ret = nb_candidate_commit(vty->candidate_config, NB_CLIENT_CLI, vty, - true, comment, &transaction_id); + context.client = NB_CLIENT_CLI; + context.user = vty; + ret = nb_candidate_commit(&context, vty->candidate_config, true, + comment, &transaction_id); /* Map northbound return code to CLI return code. */ switch (ret) { @@ -690,9 +701,12 @@ DEFPY (config_commit_check, "Commit changes into the running configuration\n" "Check if the configuration changes are valid\n") { + struct nb_context context = {}; int ret; - ret = nb_candidate_validate(vty->candidate_config); + context.client = NB_CLIENT_CLI; + context.user = vty; + ret = nb_candidate_validate(&context, vty->candidate_config); if (ret != NB_OK) { vty_out(vty, "%% Failed to validate candidate configuration.\n\n"); @@ -1530,6 +1544,7 @@ DEFPY (show_yang_module_translator, static int nb_cli_rollback_configuration(struct vty *vty, uint32_t transaction_id) { + struct nb_context context = {}; struct nb_config *candidate; char comment[80]; int ret; @@ -1544,8 +1559,9 @@ static int nb_cli_rollback_configuration(struct vty *vty, snprintf(comment, sizeof(comment), "Rollback to transaction %u", transaction_id); - ret = nb_candidate_commit(candidate, NB_CLIENT_CLI, vty, true, comment, - NULL); + context.client = NB_CLIENT_CLI; + context.user = vty; + ret = nb_candidate_commit(&context, candidate, true, comment, NULL); nb_config_free(candidate); switch (ret) { case NB_OK: diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c index 2fc3c81cf..50daa62e5 100644 --- a/lib/northbound_confd.c +++ b/lib/northbound_confd.c @@ -285,6 +285,7 @@ frr_confd_cdb_diff_iter(confd_hkeypath_t *kp, enum cdb_iter_op cdb_op, static int frr_confd_cdb_read_cb_prepare(int fd, int *subp, int reslen) { + struct nb_context context = {}; struct nb_config *candidate; struct cdb_iter_args iter_args; int ret; @@ -321,8 +322,9 @@ static int frr_confd_cdb_read_cb_prepare(int fd, int *subp, int reslen) * required to apply them. */ transaction = NULL; - ret = nb_candidate_commit_prepare(candidate, NB_CLIENT_CONFD, NULL, - NULL, &transaction); + context.client = NB_CLIENT_CONFD; + ret = nb_candidate_commit_prepare(&context, candidate, NULL, + &transaction); if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) { enum confd_errcode errcode; const char *errmsg; diff --git a/lib/northbound_db.c b/lib/northbound_db.c index 598805b96..244e760b2 100644 --- a/lib/northbound_db.c +++ b/lib/northbound_db.c @@ -86,7 +86,7 @@ int nb_db_transaction_save(const struct nb_transaction *transaction, if (!ss) goto exit; - client_name = nb_client_name(transaction->client); + client_name = nb_client_name(transaction->context->client); /* Always record configurations in the XML format. */ if (lyd_print_mem(&config_str, transaction->config->dnode, LYD_XML, LYP_FORMAT | LYP_WITHSIBLINGS) diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp index 2962a977e..b038d1011 100644 --- a/lib/northbound_grpc.cpp +++ b/lib/northbound_grpc.cpp @@ -672,13 +672,17 @@ class NorthboundImpl // Execute the user request. + struct nb_context context = {}; + context.client = NB_CLIENT_GRPC; + switch (phase) { case frr::CommitRequest::VALIDATE: - ret = nb_candidate_validate(candidate->config); + ret = nb_candidate_validate(&context, + candidate->config); break; case frr::CommitRequest::PREPARE: ret = nb_candidate_commit_prepare( - candidate->config, NB_CLIENT_GRPC, NULL, + &context, candidate->config, comment.c_str(), &candidate->transaction); break; @@ -693,8 +697,8 @@ class NorthboundImpl break; case frr::CommitRequest::ALL: ret = nb_candidate_commit( - candidate->config, NB_CLIENT_GRPC, NULL, - true, comment.c_str(), &transaction_id); + &context, candidate->config, true, + comment.c_str(), &transaction_id); break; } diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index b94c93976..4d15c80a2 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -245,6 +245,7 @@ static int frr_sr_config_change_cb_verify(sr_session_ctx_t *session, sr_change_oper_t sr_op; sr_val_t *sr_old_val, *sr_new_val; char xpath[XPATH_MAXLEN]; + struct nb_context context = {}; struct nb_config *candidate; snprintf(xpath, sizeof(xpath), "/%s:*", module_name); @@ -276,21 +277,22 @@ static int frr_sr_config_change_cb_verify(sr_session_ctx_t *session, } transaction = NULL; + context.client = NB_CLIENT_SYSREPO; if (startup_config) { /* * sysrepod sends the entire startup configuration using a * single event (SR_EV_ENABLED). This means we need to perform * the full two-phase commit protocol in one go here. */ - ret = nb_candidate_commit(candidate, NB_CLIENT_SYSREPO, NULL, - true, NULL, NULL); + ret = nb_candidate_commit(&context, candidate, true, NULL, + NULL); } else { /* * Validate the configuration changes and allocate all resources * required to apply them. */ - ret = nb_candidate_commit_prepare(candidate, NB_CLIENT_SYSREPO, - NULL, NULL, &transaction); + ret = nb_candidate_commit_prepare(&context, candidate, NULL, + &transaction); } /* Map northbound return code to sysrepo return code. */ @@ -2349,9 +2349,12 @@ static void vty_read_file(struct nb_config *config, FILE *confp) * reading the configuration file. */ if (config == NULL) { - ret = nb_candidate_commit(vty->candidate_config, NB_CLIENT_CLI, - vty, true, "Read configuration file", - NULL); + struct nb_context context = {}; + + context.client = NB_CLIENT_CLI; + context.user = vty; + ret = nb_candidate_commit(&context, vty->candidate_config, true, + "Read configuration file", NULL); if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) zlog_err("%s: failed to read configuration file.", __func__); |