summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mgmt_be_client.c136
-rw-r--r--lib/mgmt_be_client.h10
-rw-r--r--lib/mgmt_fe_client.c42
-rw-r--r--lib/mgmt_fe_client.h11
-rw-r--r--lib/mgmt_msg.c6
-rw-r--r--lib/northbound.c7
-rw-r--r--lib/northbound_cli.c13
-rw-r--r--lib/vty.c63
-rw-r--r--lib/vty.h11
9 files changed, 175 insertions, 124 deletions
diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c
index 5c875204f7..fdeff3ec0a 100644
--- a/lib/mgmt_be_client.c
+++ b/lib/mgmt_be_client.c
@@ -20,14 +20,6 @@
#include "lib/mgmt_be_client_clippy.c"
-#define MGMTD_BE_CLIENT_DBG(fmt, ...) \
- DEBUGD(&mgmt_dbg_be_client, "BE-CLIENT: %s:" fmt, __func__, \
- ##__VA_ARGS__)
-#define MGMTD_BE_CLIENT_ERR(fmt, ...) \
- zlog_err("BE-CLIENT: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#define MGMTD_DBG_BE_CLIENT_CHECK() \
- DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_ALL)
-
DEFINE_MTYPE_STATIC(LIB, MGMTD_BE_CLIENT, "backend client");
DEFINE_MTYPE_STATIC(LIB, MGMTD_BE_CLIENT_NAME, "backend client name");
DEFINE_MTYPE_STATIC(LIB, MGMTD_BE_BATCH, "backend transaction batch data");
@@ -217,14 +209,16 @@ static void mgmt_be_cleanup_all_batches(struct mgmt_be_txn_ctx *txn)
}
static struct mgmt_be_txn_ctx *
-mgmt_be_find_txn_by_id(struct mgmt_be_client *client_ctx, uint64_t txn_id)
+mgmt_be_find_txn_by_id(struct mgmt_be_client *client_ctx, uint64_t txn_id,
+ bool warn)
{
struct mgmt_be_txn_ctx *txn = NULL;
- FOREACH_BE_TXN_IN_LIST (client_ctx, txn) {
+ FOREACH_BE_TXN_IN_LIST (client_ctx, txn)
if (txn->txn_id == txn_id)
return txn;
- }
+ if (warn)
+ MGMTD_BE_CLIENT_ERR("Unknown txn-id: %" PRIu64, txn_id);
return NULL;
}
@@ -234,20 +228,21 @@ mgmt_be_txn_create(struct mgmt_be_client *client_ctx, uint64_t txn_id)
{
struct mgmt_be_txn_ctx *txn = NULL;
- txn = mgmt_be_find_txn_by_id(client_ctx, txn_id);
- if (!txn) {
- txn = XCALLOC(MTYPE_MGMTD_BE_TXN,
- sizeof(struct mgmt_be_txn_ctx));
- assert(txn);
+ txn = mgmt_be_find_txn_by_id(client_ctx, txn_id, false);
+ if (txn) {
+ MGMTD_BE_CLIENT_ERR("Can't create existing txn-id: %" PRIu64,
+ txn_id);
+ return NULL;
+ }
- txn->txn_id = txn_id;
- txn->client = client_ctx;
- mgmt_be_batches_init(&txn->cfg_batches);
- mgmt_be_batches_init(&txn->apply_cfgs);
- mgmt_be_txns_add_tail(&client_ctx->txn_head, txn);
+ txn = XCALLOC(MTYPE_MGMTD_BE_TXN, sizeof(struct mgmt_be_txn_ctx));
+ txn->txn_id = txn_id;
+ txn->client = client_ctx;
+ mgmt_be_batches_init(&txn->cfg_batches);
+ mgmt_be_batches_init(&txn->apply_cfgs);
+ mgmt_be_txns_add_tail(&client_ctx->txn_head, txn);
- MGMTD_BE_CLIENT_DBG("Added new txn-id: %" PRIu64, txn_id);
- }
+ MGMTD_BE_CLIENT_DBG("Created new txn-id: %" PRIu64, txn_id);
return txn;
}
@@ -297,7 +292,7 @@ static void mgmt_be_cleanup_all_txns(struct mgmt_be_client *client_ctx)
}
static int mgmt_be_send_txn_reply(struct mgmt_be_client *client_ctx,
- uint64_t txn_id, bool create, bool success)
+ uint64_t txn_id, bool create)
{
Mgmtd__BeMessage be_msg;
Mgmtd__BeTxnReply txn_reply;
@@ -305,7 +300,7 @@ static int mgmt_be_send_txn_reply(struct mgmt_be_client *client_ctx,
mgmtd__be_txn_reply__init(&txn_reply);
txn_reply.create = create;
txn_reply.txn_id = txn_id;
- txn_reply.success = success;
+ txn_reply.success = true;
mgmtd__be_message__init(&be_msg);
be_msg.message_case = MGMTD__BE_MESSAGE__MESSAGE_TXN_REPLY;
@@ -321,44 +316,29 @@ static int mgmt_be_process_txn_req(struct mgmt_be_client *client_ctx,
{
struct mgmt_be_txn_ctx *txn;
- txn = mgmt_be_find_txn_by_id(client_ctx, txn_id);
if (create) {
- if (txn) {
- /*
- * Transaction with same txn-id already exists.
- * Should not happen under any circumstances.
- */
- MGMTD_BE_CLIENT_ERR(
- "txn-id: %" PRIu64 " already exists", txn_id);
- mgmt_be_send_txn_reply(client_ctx, txn_id, create,
- false);
- }
+ MGMTD_BE_CLIENT_DBG("Creating new txn-id %" PRIu64, txn_id);
- MGMTD_BE_CLIENT_DBG("Created new txn-id %" PRIu64, txn_id);
txn = mgmt_be_txn_create(client_ctx, txn_id);
+ if (!txn)
+ goto failed;
if (client_ctx->cbs.txn_notify)
- (void)(*client_ctx->cbs.txn_notify)(
- client_ctx, client_ctx->user_data,
- &txn->client_data, false);
+ (*client_ctx->cbs.txn_notify)(client_ctx,
+ client_ctx->user_data,
+ &txn->client_data, false);
} else {
- if (!txn) {
- /*
- * Transaction with same txn-id does not exists.
- * Return sucess anyways.
- */
- MGMTD_BE_CLIENT_DBG("txn-id: %" PRIu64
- " for delete does NOT exists",
- txn_id);
- } else {
- MGMTD_BE_CLIENT_DBG("Delete txn-id: %" PRIu64, txn_id);
+ MGMTD_BE_CLIENT_DBG("Deleting txn-id: %" PRIu64, txn_id);
+ txn = mgmt_be_find_txn_by_id(client_ctx, txn_id, false);
+ if (txn)
mgmt_be_txn_delete(client_ctx, &txn);
- }
}
- mgmt_be_send_txn_reply(client_ctx, txn_id, create, true);
+ return mgmt_be_send_txn_reply(client_ctx, txn_id, create);
- return 0;
+failed:
+ msg_conn_disconnect(&client_ctx->client.conn, true);
+ return -1;
}
static int mgmt_be_send_cfgdata_create_reply(struct mgmt_be_client *client_ctx,
@@ -610,25 +590,23 @@ static int mgmt_be_process_cfgdata_req(struct mgmt_be_client *client_ctx,
{
struct mgmt_be_txn_ctx *txn;
- txn = mgmt_be_find_txn_by_id(client_ctx, txn_id);
- if (!txn) {
- MGMTD_BE_CLIENT_ERR("Invalid txn-id: %" PRIu64
- " from MGMTD server",
- txn_id);
- mgmt_be_send_cfgdata_create_reply(
- client_ctx, txn_id, batch_id, false,
- "Transaction context not created yet");
- } else {
- mgmt_be_update_setcfg_in_batch(client_ctx, txn, batch_id,
- cfg_req, num_req);
- }
+ txn = mgmt_be_find_txn_by_id(client_ctx, txn_id, true);
+ if (!txn)
+ goto failed;
+
+ mgmt_be_update_setcfg_in_batch(client_ctx, txn, batch_id, cfg_req,
+ num_req);
if (txn && end_of_data) {
- MGMTD_BE_CLIENT_DBG("Triggering CFG_PREPARE_REQ processing");
- mgmt_be_txn_cfg_prepare(txn);
+ MGMTD_BE_CLIENT_DBG("End of data; CFG_PREPARE_REQ processing");
+ if (mgmt_be_txn_cfg_prepare(txn))
+ goto failed;
}
return 0;
+failed:
+ msg_conn_disconnect(&client_ctx->client.conn, true);
+ return -1;
}
static int mgmt_be_send_apply_reply(struct mgmt_be_client *client_ctx,
@@ -731,23 +709,28 @@ static int mgmt_be_process_cfg_apply(struct mgmt_be_client *client_ctx,
{
struct mgmt_be_txn_ctx *txn;
- txn = mgmt_be_find_txn_by_id(client_ctx, txn_id);
- if (!txn) {
- mgmt_be_send_apply_reply(client_ctx, txn_id, NULL, 0, false,
- "Transaction not created yet!");
- return -1;
- }
+ txn = mgmt_be_find_txn_by_id(client_ctx, txn_id, true);
+ if (!txn)
+ goto failed;
MGMTD_BE_CLIENT_DBG("Trigger CFG_APPLY_REQ processing");
- mgmt_be_txn_proc_cfgapply(txn);
+ if (mgmt_be_txn_proc_cfgapply(txn))
+ goto failed;
return 0;
+failed:
+ msg_conn_disconnect(&client_ctx->client.conn, true);
+ return -1;
}
+
static int mgmt_be_client_handle_msg(struct mgmt_be_client *client_ctx,
Mgmtd__BeMessage *be_msg)
{
/*
+ * On error we may have closed the connection so don't do anything with
+ * the client_ctx on return.
+ *
* protobuf-c adds a max size enum with an internal, and changing by
* version, name; cast to an int to avoid unhandled enum warnings
*/
@@ -888,6 +871,11 @@ static int _notify_conenct_disconnect(struct msg_client *msg_client,
if (client->cbs.client_connect_notify)
(void)(*client->cbs.client_connect_notify)(
client, client->user_data, connected);
+
+ /* Cleanup any in-progress TXN on disconnect */
+ if (!connected)
+ mgmt_be_cleanup_all_txns(client);
+
return 0;
}
diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h
index 4d8a1f51a1..4ad5ca5957 100644
--- a/lib/mgmt_be_client.h
+++ b/lib/mgmt_be_client.h
@@ -131,10 +131,20 @@ mgmt_be_client_name2id(const char *name)
return MGMTD_BE_CLIENT_ID_MAX;
}
+extern struct debug mgmt_dbg_be_client;
+
/***************************************************************
* API prototypes
***************************************************************/
+#define MGMTD_BE_CLIENT_DBG(fmt, ...) \
+ DEBUGD(&mgmt_dbg_be_client, "BE-CLIENT: %s: " fmt, __func__, \
+ ##__VA_ARGS__)
+#define MGMTD_BE_CLIENT_ERR(fmt, ...) \
+ zlog_err("BE-CLIENT: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
+#define MGMTD_DBG_BE_CLIENT_CHECK() \
+ DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_ALL)
+
/**
* Create backend client and connect to MGMTD.
*
diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c
index 35a6d7d909..be7263f21b 100644
--- a/lib/mgmt_fe_client.c
+++ b/lib/mgmt_fe_client.c
@@ -50,6 +50,22 @@ struct mgmt_fe_client {
struct debug mgmt_dbg_fe_client = {0, "Management frontend client operations"};
+static inline const char *dsid2name(Mgmtd__DatastoreId id)
+{
+ switch ((int)id) {
+ case MGMTD_DS_NONE:
+ return "none";
+ case MGMTD_DS_RUNNING:
+ return "running";
+ case MGMTD_DS_CANDIDATE:
+ return "candidate";
+ case MGMTD_DS_OPERATIONAL:
+ return "operational";
+ default:
+ return "unknown-datastore-id";
+ }
+}
+
static struct mgmt_fe_client_session *
mgmt_fe_find_session_by_client_id(struct mgmt_fe_client *client,
uint64_t client_id)
@@ -124,18 +140,15 @@ static int mgmt_fe_send_session_req(struct mgmt_fe_client *client,
{
Mgmtd__FeMessage fe_msg;
Mgmtd__FeSessionReq sess_req;
- bool scok;
mgmtd__fe_session_req__init(&sess_req);
sess_req.create = create;
if (create) {
sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID;
sess_req.client_conn_id = session->client_id;
- scok = true;
} else {
sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_SESSION_ID;
sess_req.session_id = session->session_id;
- scok = false;
}
mgmtd__fe_message__init(&fe_msg);
@@ -146,7 +159,7 @@ static int mgmt_fe_send_session_req(struct mgmt_fe_client *client,
"Sending SESSION_REQ %s message for client-id %" PRIu64,
create ? "create" : "destroy", session->client_id);
- return mgmt_fe_client_send_msg(client, &fe_msg, scok);
+ return mgmt_fe_client_send_msg(client, &fe_msg, true);
}
int mgmt_fe_send_lockds_req(struct mgmt_fe_client *client, uint64_t session_id,
@@ -168,8 +181,9 @@ int mgmt_fe_send_lockds_req(struct mgmt_fe_client *client, uint64_t session_id,
fe_msg.lockds_req = &lockds_req;
MGMTD_FE_CLIENT_DBG(
- "Sending %sLOCK_REQ message for Ds:%d session-id %" PRIu64,
- lock ? "" : "UN", ds_id, session_id);
+ "Sending LOCKDS_REQ (%sLOCK) message for DS:%s session-id %" PRIu64,
+ lock ? "" : "UN", dsid2name(ds_id), session_id);
+
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
@@ -197,9 +211,9 @@ int mgmt_fe_send_setcfg_req(struct mgmt_fe_client *client, uint64_t session_id,
fe_msg.setcfg_req = &setcfg_req;
MGMTD_FE_CLIENT_DBG(
- "Sending SET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
+ "Sending SET_CONFIG_REQ message for DS:%s session-id %" PRIu64
" (#xpaths:%d)",
- ds_id, session_id, num_data_reqs);
+ dsid2name(ds_id), session_id, num_data_reqs);
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
@@ -227,8 +241,8 @@ int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client *client,
fe_msg.commcfg_req = &commitcfg_req;
MGMTD_FE_CLIENT_DBG(
- "Sending COMMIT_CONFIG_REQ message for Src-Ds:%d, Dst-Ds:%d session-id %" PRIu64,
- src_ds_id, dest_ds_id, session_id);
+ "Sending COMMIT_CONFIG_REQ message for Src-DS:%s, Dst-DS:%s session-id %" PRIu64,
+ dsid2name(src_ds_id), dsid2name(dest_ds_id), session_id);
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
@@ -254,9 +268,9 @@ int mgmt_fe_send_getcfg_req(struct mgmt_fe_client *client, uint64_t session_id,
fe_msg.getcfg_req = &getcfg_req;
MGMTD_FE_CLIENT_DBG(
- "Sending GET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
+ "Sending GET_CONFIG_REQ message for DS:%s session-id %" PRIu64
" (#xpaths:%d)",
- ds_id, session_id, num_data_reqs);
+ dsid2name(ds_id), session_id, num_data_reqs);
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
@@ -282,9 +296,9 @@ int mgmt_fe_send_getdata_req(struct mgmt_fe_client *client, uint64_t session_id,
fe_msg.getdata_req = &getdata_req;
MGMTD_FE_CLIENT_DBG(
- "Sending GET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
+ "Sending GET_CONFIG_REQ message for DS:%s session-id %" PRIu64
" (#xpaths:%d)",
- ds_id, session_id, num_data_reqs);
+ dsid2name(ds_id), session_id, num_data_reqs);
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
diff --git a/lib/mgmt_fe_client.h b/lib/mgmt_fe_client.h
index edf861746c..b0ac44bb3e 100644
--- a/lib/mgmt_fe_client.h
+++ b/lib/mgmt_fe_client.h
@@ -119,19 +119,18 @@ struct mgmt_fe_client_cbs {
extern struct debug mgmt_dbg_fe_client;
+/***************************************************************
+ * API prototypes
+ ***************************************************************/
+
#define MGMTD_FE_CLIENT_DBG(fmt, ...) \
- DEBUGD(&mgmt_dbg_fe_client, "FE-CLIENT: %s:" fmt, __func__, \
+ DEBUGD(&mgmt_dbg_fe_client, "FE-CLIENT: %s: " fmt, __func__, \
##__VA_ARGS__)
#define MGMTD_FE_CLIENT_ERR(fmt, ...) \
zlog_err("FE-CLIENT: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
#define MGMTD_DBG_FE_CLIENT_CHECK() \
DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_ALL)
-
-/***************************************************************
- * API prototypes
- ***************************************************************/
-
/*
* Initialize library and try connecting with MGMTD FrontEnd interface.
*
diff --git a/lib/mgmt_msg.c b/lib/mgmt_msg.c
index 0d9802a2b3..ba69c20aba 100644
--- a/lib/mgmt_msg.c
+++ b/lib/mgmt_msg.c
@@ -59,11 +59,12 @@ enum mgmt_msg_rsched mgmt_msg_read(struct mgmt_msg_state *ms, int fd,
*/
while (avail > sizeof(struct mgmt_msg_hdr)) {
n = stream_read_try(ms->ins, fd, avail);
- MGMT_MSG_DBG(dbgtag, "got %zd bytes", n);
/* -2 is normal nothing read, and to retry */
- if (n == -2)
+ if (n == -2) {
+ MGMT_MSG_DBG(dbgtag, "nothing more to read");
break;
+ }
if (n <= 0) {
if (n == 0)
MGMT_MSG_ERR(ms, "got EOF/disconnect");
@@ -73,6 +74,7 @@ enum mgmt_msg_rsched mgmt_msg_read(struct mgmt_msg_state *ms, int fd,
safe_strerror(errno));
return MSR_DISCONNECT;
}
+ MGMT_MSG_DBG(dbgtag, "read %zd bytes", n);
ms->nrxb += n;
avail -= n;
}
diff --git a/lib/northbound.c b/lib/northbound.c
index 775f6ff92f..ef2344ee11 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -792,18 +792,19 @@ static void nb_update_candidate_changes(struct nb_config *candidate,
LYD_TREE_DFS_BEGIN (root, dnode) {
op = nb_lyd_diff_get_op(dnode);
switch (op) {
- case 'c':
+ case 'c': /* create */
nb_config_diff_created(dnode, seq, cfg_chgs);
LYD_TREE_DFS_continue = 1;
break;
- case 'd':
+ case 'd': /* delete */
nb_config_diff_deleted(dnode, seq, cfg_chgs);
LYD_TREE_DFS_continue = 1;
break;
- case 'r':
+ case 'r': /* replace */
nb_config_diff_add_change(cfg_chgs, NB_OP_MODIFY, seq,
dnode);
break;
+ case 'n': /* none */
default:
break;
}
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index e9c89d2029..9d6ec66689 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -202,7 +202,7 @@ int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
return CMD_SUCCESS;
implicit_commit = vty_needs_implicit_commit(vty);
- ret = vty_mgmt_send_config_data(vty);
+ ret = vty_mgmt_send_config_data(vty, implicit_commit);
if (ret >= 0 && !implicit_commit)
vty->mgmt_num_pending_setcfg++;
return ret;
@@ -229,9 +229,16 @@ int nb_cli_apply_changes_clear_pending(struct vty *vty,
if (vty_mgmt_should_process_cli_apply_changes(vty)) {
VTY_CHECK_XPATH;
-
+ /*
+ * The legacy user wanted to clear pending (i.e., perform a
+ * commit immediately) due to some non-yang compatible
+ * functionality. This new mgmtd code however, continues to send
+ * changes putting off the commit until XFRR_end is received
+ * (i.e., end-of-config-file). This should be fine b/c all
+ * conversions to mgmtd require full proper implementations.
+ */
implicit_commit = vty_needs_implicit_commit(vty);
- ret = vty_mgmt_send_config_data(vty);
+ ret = vty_mgmt_send_config_data(vty, implicit_commit);
if (ret >= 0 && !implicit_commit)
vty->mgmt_num_pending_setcfg++;
return ret;
diff --git a/lib/vty.c b/lib/vty.c
index b701f3bc0f..fd00e11c5f 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -134,18 +134,22 @@ void vty_mgmt_resume_response(struct vty *vty, bool success)
uint8_t header[4] = {0, 0, 0, 0};
int ret = CMD_SUCCESS;
- if (!vty->mgmt_req_pending) {
+ if (!vty->mgmt_req_pending_cmd) {
zlog_err(
- "vty response called without setting mgmt_req_pending");
+ "vty resume response called without mgmt_req_pending_cmd");
return;
}
if (!success)
ret = CMD_WARNING_CONFIG_FAILED;
- vty->mgmt_req_pending = false;
+ MGMTD_FE_CLIENT_DBG(
+ "resuming CLI cmd after %s on vty session-id: %" PRIu64
+ " with '%s'",
+ vty->mgmt_req_pending_cmd, vty->mgmt_session_id,
+ success ? "succeeded" : "failed");
- MGMTD_FE_CLIENT_DBG("resuming: %s:", success ? "succeeded" : "failed");
+ vty->mgmt_req_pending_cmd = NULL;
if (vty->type != VTY_FILE) {
header[3] = ret;
@@ -2217,6 +2221,8 @@ bool mgmt_vty_read_configs(void)
line_num = 0;
(void)config_from_file(vty, confp, &line_num);
count++;
+
+ fclose(confp);
}
snprintf(path, sizeof(path), "%s/mgmtd.conf", frr_sysconfdir);
@@ -2240,6 +2246,8 @@ bool mgmt_vty_read_configs(void)
line_num = 0;
(void)config_from_file(vty, confp, &line_num);
count++;
+
+ fclose(confp);
}
vty->pending_allowed = false;
@@ -2270,6 +2278,19 @@ static void vtysh_read(struct event *thread)
sock = EVENT_FD(thread);
vty = EVENT_ARG(thread);
+ /*
+ * This code looks like it can read multiple commands from the `buf`
+ * value returned by read(); however, it cannot in some cases.
+ *
+ * There are multiple paths out of the "copying to vty->buf" loop, which
+ * lose any content not yet copied from the stack `buf`, `passfd`,
+ * `CMD_SUSPEND` and finally if a front-end for mgmtd (generally this
+ * would be mgmtd itself). So these code paths are counting on vtysh not
+ * sending us more than 1 command line before waiting on the reply to
+ * that command.
+ */
+ assert(vty->type == VTY_SHELL_SERV);
+
if ((nbytes = read(sock, buf, VTY_READ_BUFSIZ)) <= 0) {
if (nbytes < 0) {
if (ERRNO_IO_RETRY(errno)) {
@@ -2344,8 +2365,13 @@ static void vtysh_read(struct event *thread)
/* with new infra we need to stop response till
* we get response through callback.
*/
- if (vty->mgmt_req_pending)
+ if (vty->mgmt_req_pending_cmd) {
+ MGMTD_FE_CLIENT_DBG(
+ "postpone CLI cmd response pending mgmtd %s on vty session-id %" PRIu64,
+ vty->mgmt_req_pending_cmd,
+ vty->mgmt_session_id);
return;
+ }
/* warning: watchfrr hardcodes this result write
*/
@@ -2419,7 +2445,16 @@ void vty_close(struct vty *vty)
vty->status = VTY_CLOSE;
+ /*
+ * If we reach here with pending config to commit we will be losing it
+ * so warn the user.
+ */
+ if (vty->mgmt_num_pending_setcfg)
+ MGMTD_FE_CLIENT_ERR(
+ "vty closed, uncommitted config will be lost.");
+
if (mgmt_fe_client && vty->mgmt_session_id) {
+ MGMTD_FE_CLIENT_DBG("closing vty session");
mgmt_fe_destroy_client_session(mgmt_fe_client,
vty->mgmt_client_id);
vty->mgmt_session_id = 0;
@@ -3440,7 +3475,9 @@ static void vty_mgmt_session_notify(struct mgmt_fe_client *client,
vty->mgmt_session_id = session_id;
} else {
vty->mgmt_session_id = 0;
- vty_close(vty);
+ /* We may come here by way of vty_close() and short-circuits */
+ if (vty->status != VTY_CLOSE)
+ vty_close(vty);
}
}
@@ -3609,13 +3646,13 @@ int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id,
return -1;
}
- vty->mgmt_req_pending = true;
+ vty->mgmt_req_pending_cmd = "MESSAGE_LOCKDS_REQ";
}
return 0;
}
-int vty_mgmt_send_config_data(struct vty *vty)
+int vty_mgmt_send_config_data(struct vty *vty, bool implicit_commit)
{
Mgmtd__YangDataValue value[VTY_MAXCFGCHANGES];
Mgmtd__YangData cfg_data[VTY_MAXCFGCHANGES];
@@ -3623,7 +3660,6 @@ int vty_mgmt_send_config_data(struct vty *vty)
Mgmtd__YangCfgDataReq *cfgreq[VTY_MAXCFGCHANGES] = {0};
size_t indx;
int cnt;
- bool implicit_commit = false;
if (vty->type == VTY_FILE) {
/*
@@ -3697,7 +3733,6 @@ int vty_mgmt_send_config_data(struct vty *vty)
}
vty->mgmt_req_id++;
- implicit_commit = vty_needs_implicit_commit(vty);
if (cnt && mgmt_fe_send_setcfg_req(
mgmt_fe_client, vty->mgmt_session_id,
vty->mgmt_req_id, MGMTD_DS_CANDIDATE, cfgreq,
@@ -3709,7 +3744,7 @@ int vty_mgmt_send_config_data(struct vty *vty)
return -1;
}
- vty->mgmt_req_pending = true;
+ vty->mgmt_req_pending_cmd = "MESSAGE_SETCFG_REQ";
}
return 0;
@@ -3729,7 +3764,7 @@ int vty_mgmt_send_commit_config(struct vty *vty, bool validate_only, bool abort)
return -1;
}
- vty->mgmt_req_pending = true;
+ vty->mgmt_req_pending_cmd = "MESSAGE_COMMCFG_REQ";
vty->mgmt_num_pending_setcfg = 0;
}
@@ -3766,7 +3801,7 @@ int vty_mgmt_send_get_config(struct vty *vty, Mgmtd__DatastoreId datastore,
return -1;
}
- vty->mgmt_req_pending = true;
+ vty->mgmt_req_pending_cmd = "MESSAGE_GETCFG_REQ";
return 0;
}
@@ -3800,7 +3835,7 @@ int vty_mgmt_send_get_data(struct vty *vty, Mgmtd__DatastoreId datastore,
return -1;
}
- vty->mgmt_req_pending = true;
+ vty->mgmt_req_pending_cmd = "MESSAGE_GETDATA_REQ";
return 0;
}
diff --git a/lib/vty.h b/lib/vty.h
index 28f27d0d47..3b651d20a2 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -147,7 +147,6 @@ struct vty {
/* Dynamic transaction information. */
bool pending_allowed;
bool pending_commit;
- bool no_implicit_commit;
char *pending_cmds_buf;
size_t pending_cmds_buflen;
size_t pending_cmds_bufpos;
@@ -229,7 +228,7 @@ struct vty {
/* set when we have sent mgmtd a *REQ command in response to some vty
* CLI command and we are waiting on the reply so we can respond to the
* vty user. */
- bool mgmt_req_pending;
+ const char *mgmt_req_pending_cmd;
bool mgmt_locked_candidate_ds;
};
@@ -408,7 +407,7 @@ extern bool vty_mgmt_fe_enabled(void);
extern bool vty_mgmt_should_process_cli_apply_changes(struct vty *vty);
extern bool mgmt_vty_read_configs(void);
-extern int vty_mgmt_send_config_data(struct vty *vty);
+extern int vty_mgmt_send_config_data(struct vty *vty, bool implicit_commit);
extern int vty_mgmt_send_commit_config(struct vty *vty, bool validate_only,
bool abort);
extern int vty_mgmt_send_get_config(struct vty *vty,
@@ -422,11 +421,7 @@ extern void vty_mgmt_resume_response(struct vty *vty, bool success);
static inline bool vty_needs_implicit_commit(struct vty *vty)
{
- return (frr_get_cli_mode() == FRR_CLI_CLASSIC
- ? ((vty->pending_allowed || vty->no_implicit_commit)
- ? false
- : true)
- : false);
+ return frr_get_cli_mode() == FRR_CLI_CLASSIC && !vty->pending_allowed;
}
#ifdef __cplusplus