summaryrefslogtreecommitdiffstats
path: root/mgmtd/mgmt_fe_adapter.c
diff options
context:
space:
mode:
Diffstat (limited to 'mgmtd/mgmt_fe_adapter.c')
-rw-r--r--mgmtd/mgmt_fe_adapter.c596
1 files changed, 454 insertions, 142 deletions
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c
index 2b2471c..ec8e773 100644
--- a/mgmtd/mgmt_fe_adapter.c
+++ b/mgmtd/mgmt_fe_adapter.c
@@ -8,11 +8,13 @@
*/
#include <zebra.h>
+#include "darr.h"
#include "sockopt.h"
#include "network.h"
#include "libfrr.h"
#include "mgmt_fe_client.h"
#include "mgmt_msg.h"
+#include "mgmt_msg_native.h"
#include "mgmt_pb.h"
#include "hash.h"
#include "jhash.h"
@@ -21,9 +23,9 @@
#include "mgmtd/mgmt_memory.h"
#include "mgmtd/mgmt_fe_adapter.h"
-#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \
+#define __dbg(fmt, ...) \
DEBUGD(&mgmt_debug_fe, "FE-ADAPTER: %s: " fmt, __func__, ##__VA_ARGS__)
-#define MGMTD_FE_ADAPTER_ERR(fmt, ...) \
+#define __log_err(fmt, ...) \
zlog_err("FE-ADAPTER: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
#define FOREACH_ADAPTER_IN_LIST(adapter) \
@@ -76,20 +78,18 @@ mgmt_fe_session_write_lock_ds(Mgmtd__DatastoreId ds_id,
session->session_id, mgmt_ds_id2name(ds_id));
else {
if (mgmt_ds_lock(ds_ctx, session->session_id)) {
- MGMTD_FE_ADAPTER_DBG(
- "Failed to lock the DS:%s for session-id: %" PRIu64
- " from %s!",
- mgmt_ds_id2name(ds_id), session->session_id,
- session->adapter->name);
+ __dbg("Failed to lock the DS:%s for session-id: %" PRIu64
+ " from %s!",
+ mgmt_ds_id2name(ds_id), session->session_id,
+ session->adapter->name);
return -1;
}
session->ds_locked[ds_id] = true;
- MGMTD_FE_ADAPTER_DBG(
- "Write-Locked the DS:%s for session-id: %" PRIu64
- " from %s",
- mgmt_ds_id2name(ds_id), session->session_id,
- session->adapter->name);
+ __dbg("Write-Locked the DS:%s for session-id: %" PRIu64
+ " from %s",
+ mgmt_ds_id2name(ds_id), session->session_id,
+ session->adapter->name);
}
return 0;
@@ -105,11 +105,10 @@ static void mgmt_fe_session_unlock_ds(Mgmtd__DatastoreId ds_id,
session->ds_locked[ds_id] = false;
mgmt_ds_unlock(ds_ctx);
- MGMTD_FE_ADAPTER_DBG(
- "Unlocked DS:%s write-locked earlier by session-id: %" PRIu64
- " from %s",
- mgmt_ds_id2name(ds_id), session->session_id,
- session->adapter->name);
+ __dbg("Unlocked DS:%s write-locked earlier by session-id: %" PRIu64
+ " from %s",
+ mgmt_ds_id2name(ds_id), session->session_id,
+ session->adapter->name);
}
static void
@@ -204,14 +203,13 @@ mgmt_fe_find_session_by_client_id(struct mgmt_fe_client_adapter *adapter,
FOREACH_SESSION_IN_LIST (adapter, session) {
if (session->client_id == client_id) {
- MGMTD_FE_ADAPTER_DBG("Found session-id %" PRIu64
- " using client-id %" PRIu64,
- session->session_id, client_id);
+ __dbg("Found session-id %" PRIu64
+ " using client-id %" PRIu64,
+ session->session_id, client_id);
return session;
}
}
- MGMTD_FE_ADAPTER_DBG("Session not found using client-id %" PRIu64,
- client_id);
+ __dbg("Session not found using client-id %" PRIu64, client_id);
return NULL;
}
@@ -246,6 +244,23 @@ mgmt_session_id2ctx(uint64_t session_id)
return session;
}
+void mgmt_fe_adapter_toggle_client_debug(bool set)
+{
+ struct mgmt_fe_client_adapter *adapter;
+
+ FOREACH_ADAPTER_IN_LIST (adapter)
+ adapter->conn->debug = set;
+}
+
+static struct mgmt_fe_session_ctx *fe_adapter_session_by_txn_id(uint64_t txn_id)
+{
+ uint64_t session_id = mgmt_txn_get_session_id(txn_id);
+
+ if (session_id == MGMTD_SESSION_ID_NONE)
+ return NULL;
+ return mgmt_session_id2ctx(session_id);
+}
+
static struct mgmt_fe_session_ctx *
mgmt_fe_create_session(struct mgmt_fe_client_adapter *adapter,
uint64_t client_id)
@@ -273,6 +288,14 @@ mgmt_fe_create_session(struct mgmt_fe_client_adapter *adapter,
return session;
}
+static int fe_adapter_send_native_msg(struct mgmt_fe_client_adapter *adapter,
+ void *msg, size_t len,
+ bool short_circuit_ok)
+{
+ return msg_conn_send_msg(adapter->conn, MGMT_MSG_VERSION_NATIVE, msg,
+ len, NULL, short_circuit_ok);
+}
+
static int fe_adapter_send_msg(struct mgmt_fe_client_adapter *adapter,
Mgmtd__FeMessage *fe_msg, bool short_circuit_ok)
{
@@ -303,9 +326,8 @@ static int fe_adapter_send_session_reply(struct mgmt_fe_client_adapter *adapter,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY;
fe_msg.session_reply = &session_reply;
- MGMTD_FE_ADAPTER_DBG(
- "Sending SESSION_REPLY message to MGMTD Frontend client '%s'",
- adapter->name);
+ __dbg("Sending SESSION_REPLY message to MGMTD Frontend client '%s'",
+ adapter->name);
return fe_adapter_send_msg(adapter, &fe_msg, true);
}
@@ -334,9 +356,8 @@ static int fe_adapter_send_lockds_reply(struct mgmt_fe_session_ctx *session,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY;
fe_msg.lockds_reply = &lockds_reply;
- MGMTD_FE_ADAPTER_DBG(
- "Sending LOCK_DS_REPLY message to MGMTD Frontend client '%s' scok: %d",
- session->adapter->name, scok);
+ __dbg("Sending LOCK_DS_REPLY message to MGMTD Frontend client '%s' scok: %d",
+ session->adapter->name, scok);
return fe_adapter_send_msg(session->adapter, &fe_msg, scok);
}
@@ -369,9 +390,8 @@ static int fe_adapter_send_set_cfg_reply(struct mgmt_fe_session_ctx *session,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY;
fe_msg.setcfg_reply = &setcfg_reply;
- MGMTD_FE_ADAPTER_DBG(
- "Sending SETCFG_REPLY message to MGMTD Frontend client '%s'",
- session->adapter->name);
+ __dbg("Sending SETCFG_REPLY message to MGMTD Frontend client '%s'",
+ session->adapter->name);
if (implicit_commit) {
if (mm->perf_stats_en)
@@ -415,9 +435,8 @@ static int fe_adapter_send_commit_cfg_reply(
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY;
fe_msg.commcfg_reply = &commcfg_reply;
- MGMTD_FE_ADAPTER_DBG(
- "Sending COMMIT_CONFIG_REPLY message to MGMTD Frontend client '%s'",
- session->adapter->name);
+ __dbg("Sending COMMIT_CONFIG_REPLY message to MGMTD Frontend client '%s'",
+ session->adapter->name);
/*
* Cleanup the CONFIG transaction associated with this session.
@@ -457,8 +476,8 @@ static int fe_adapter_send_get_reply(struct mgmt_fe_session_ctx *session,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GET_REPLY;
fe_msg.get_reply = &get_reply;
- MGMTD_FE_ADAPTER_DBG("Sending GET_REPLY message to MGMTD Frontend client '%s'",
- session->adapter->name);
+ __dbg("Sending GET_REPLY message to MGMTD Frontend client '%s'",
+ session->adapter->name);
/*
* Cleanup the SHOW transaction associated with this session.
@@ -470,6 +489,28 @@ static int fe_adapter_send_get_reply(struct mgmt_fe_session_ctx *session,
return fe_adapter_send_msg(session->adapter, &fe_msg, false);
}
+static int fe_adapter_send_error(struct mgmt_fe_session_ctx *session,
+ uint64_t req_id, bool short_circuit_ok,
+ int16_t error, const char *errfmt, ...)
+ PRINTFRR(5, 6);
+
+static int fe_adapter_send_error(struct mgmt_fe_session_ctx *session,
+ uint64_t req_id, bool short_circuit_ok,
+ int16_t error, const char *errfmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, errfmt);
+ ret = vmgmt_msg_native_send_error(session->adapter->conn,
+ session->session_id, req_id,
+ short_circuit_ok, error, errfmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+
static void mgmt_fe_session_cfg_txn_clnup(struct event *thread)
{
struct mgmt_fe_session_ctx *session;
@@ -523,7 +564,7 @@ mgmt_fe_find_adapter_by_fd(int conn_fd)
static void mgmt_fe_adapter_delete(struct mgmt_fe_client_adapter *adapter)
{
struct mgmt_fe_session_ctx *session;
- MGMTD_FE_ADAPTER_DBG("deleting client adapter '%s'", adapter->name);
+ __dbg("deleting client adapter '%s'", adapter->name);
/* TODO: notify about client disconnect for appropriate cleanup */
FOREACH_SESSION_IN_LIST (adapter, session)
@@ -538,8 +579,7 @@ static int mgmt_fe_adapter_notify_disconnect(struct msg_conn *conn)
{
struct mgmt_fe_client_adapter *adapter = conn->user;
- MGMTD_FE_ADAPTER_DBG("notify disconnect for client adapter '%s'",
- adapter->name);
+ __dbg("notify disconnect for client adapter '%s'", adapter->name);
mgmt_fe_adapter_delete(adapter);
@@ -560,10 +600,8 @@ mgmt_fe_adapter_cleanup_old_conn(struct mgmt_fe_client_adapter *adapter)
if (strncmp(adapter->name, old->name, sizeof(adapter->name)))
continue;
- MGMTD_FE_ADAPTER_DBG(
- "Client '%s' (FD:%d) seems to have reconnected. Removing old connection (FD:%d)",
- adapter->name, adapter->conn->fd,
- old->conn->fd);
+ __dbg("Client '%s' (FD:%d) seems to have reconnected. Removing old connection (FD:%d)",
+ adapter->name, adapter->conn->fd, old->conn->fd);
msg_conn_disconnect(old->conn, false);
}
}
@@ -616,11 +654,10 @@ mgmt_fe_session_handle_lockds_req_msg(struct mgmt_fe_session_ctx *session,
if (fe_adapter_send_lockds_reply(session, lockds_req->ds_id,
lockds_req->req_id, lockds_req->lock,
true, NULL) != 0) {
- MGMTD_FE_ADAPTER_DBG(
- "Failed to send LOCK_DS_REPLY for DS %u session-id: %" PRIu64
- " from %s",
- lockds_req->ds_id, session->session_id,
- session->adapter->name);
+ __dbg("Failed to send LOCK_DS_REPLY for DS %u session-id: %" PRIu64
+ " from %s",
+ lockds_req->ds_id, session->session_id,
+ session->adapter->name);
}
return 0;
@@ -674,9 +711,6 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
}
if (session->cfg_txn_id == MGMTD_TXN_ID_NONE) {
- /* as we have the lock no-one else should have a config txn */
- assert(mgmt_config_txn_in_progress() == MGMTD_SESSION_ID_NONE);
-
/* Start a CONFIG Transaction (if not started already) */
session->cfg_txn_id = mgmt_create_txn(session->session_id,
MGMTD_TXN_TYPE_CONFIG);
@@ -690,14 +724,13 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
}
txn_created = true;
- MGMTD_FE_ADAPTER_DBG("Created new Config txn-id: %" PRIu64
- " for session-id %" PRIu64,
- session->cfg_txn_id, session->session_id);
+ __dbg("Created new Config txn-id: %" PRIu64
+ " for session-id %" PRIu64,
+ session->cfg_txn_id, session->session_id);
} else {
- MGMTD_FE_ADAPTER_DBG("Config txn-id: %" PRIu64
- " for session-id: %" PRIu64
- " already created",
- session->cfg_txn_id, session->session_id);
+ __dbg("Config txn-id: %" PRIu64 " for session-id: %" PRIu64
+ " already created",
+ session->cfg_txn_id, session->session_id);
if (setcfg_req->implicit_commit) {
/*
@@ -740,14 +773,8 @@ static int mgmt_fe_session_handle_get_req_msg(struct mgmt_fe_session_ctx *sessio
struct nb_config *cfg_root = NULL;
Mgmtd__DatastoreId ds_id = get_req->ds_id;
uint64_t req_id = get_req->req_id;
- bool is_cfg = get_req->config;
- bool ds_ok = true;
-
- if (is_cfg && ds_id != MGMTD_DS_CANDIDATE && ds_id != MGMTD_DS_RUNNING)
- ds_ok = false;
- else if (!is_cfg && ds_id != MGMTD_DS_OPERATIONAL)
- ds_ok = false;
- if (!ds_ok) {
+
+ if (ds_id != MGMTD_DS_CANDIDATE && ds_id != MGMTD_DS_RUNNING) {
fe_adapter_send_get_reply(session, ds_id, req_id, false, NULL,
"get-req on unsupported datastore");
return 0;
@@ -768,23 +795,22 @@ static int mgmt_fe_session_handle_get_req_msg(struct mgmt_fe_session_ctx *sessio
return -1;
}
- MGMTD_FE_ADAPTER_DBG("Created new show txn-id: %" PRIu64
- " for session-id: %" PRIu64,
- session->txn_id, session->session_id);
+ __dbg("Created new show txn-id: %" PRIu64
+ " for session-id: %" PRIu64,
+ session->txn_id, session->session_id);
} else {
fe_adapter_send_get_reply(session, ds_id, req_id, false, NULL,
"Request processing for GET failed!");
- MGMTD_FE_ADAPTER_DBG("Transaction in progress txn-id: %" PRIu64
- " for session-id: %" PRIu64,
- session->txn_id, session->session_id);
+ __dbg("Transaction in progress txn-id: %" PRIu64
+ " for session-id: %" PRIu64,
+ session->txn_id, session->session_id);
return -1;
}
/*
* Get a copy of the datastore config root, avoids locking.
*/
- if (is_cfg)
- cfg_root = nb_config_dup(mgmt_ds_get_nb_config(ds_ctx));
+ cfg_root = nb_config_dup(mgmt_ds_get_nb_config(ds_ctx));
/*
* Create a GET request under the transaction.
@@ -848,6 +874,9 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
}
if (session->cfg_txn_id == MGMTD_TXN_ID_NONE) {
+ /* as we have the lock no-one else should have a config txn */
+ assert(!mgmt_config_txn_in_progress());
+
/*
* Start a CONFIG Transaction (if not started already)
*/
@@ -861,10 +890,9 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
"Failed to create a Configuration session!");
return 0;
}
- MGMTD_FE_ADAPTER_DBG("Created txn-id: %" PRIu64
- " for session-id %" PRIu64
- " for COMMIT-CFG-REQ",
- session->cfg_txn_id, session->session_id);
+ __dbg("Created txn-id: %" PRIu64 " for session-id %" PRIu64
+ " for COMMIT-CFG-REQ",
+ session->cfg_txn_id, session->session_id);
}
/*
@@ -898,8 +926,8 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
*/
switch ((int)fe_msg->message_case) {
case MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ:
- MGMTD_FE_ADAPTER_DBG("Got REGISTER_REQ from '%s'",
- fe_msg->register_req->client_name);
+ __dbg("Got REGISTER_REQ from '%s'",
+ fe_msg->register_req->client_name);
if (strlen(fe_msg->register_req->client_name)) {
strlcpy(adapter->name,
@@ -912,11 +940,10 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
if (fe_msg->session_req->create
&& fe_msg->session_req->id_case
== MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID) {
- MGMTD_FE_ADAPTER_DBG(
- "Got SESSION_REQ (create) for client-id %" PRIu64
- " from '%s'",
- fe_msg->session_req->client_conn_id,
- adapter->name);
+ __dbg("Got SESSION_REQ (create) for client-id %" PRIu64
+ " from '%s'",
+ fe_msg->session_req->client_conn_id,
+ adapter->name);
session = mgmt_fe_create_session(
adapter, fe_msg->session_req->client_conn_id);
@@ -926,10 +953,9 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
!fe_msg->session_req->create
&& fe_msg->session_req->id_case
== MGMTD__FE_SESSION_REQ__ID_SESSION_ID) {
- MGMTD_FE_ADAPTER_DBG(
- "Got SESSION_REQ (destroy) for session-id %" PRIu64
- "from '%s'",
- fe_msg->session_req->session_id, adapter->name);
+ __dbg("Got SESSION_REQ (destroy) for session-id %" PRIu64
+ "from '%s'",
+ fe_msg->session_req->session_id, adapter->name);
session = mgmt_session_id2ctx(
fe_msg->session_req->session_id);
@@ -941,12 +967,11 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ:
session = mgmt_session_id2ctx(
fe_msg->lockds_req->session_id);
- MGMTD_FE_ADAPTER_DBG(
- "Got LOCKDS_REQ (%sLOCK) for DS:%s for session-id %" PRIu64
- " from '%s'",
- fe_msg->lockds_req->lock ? "" : "UN",
- mgmt_ds_id2name(fe_msg->lockds_req->ds_id),
- fe_msg->lockds_req->session_id, adapter->name);
+ __dbg("Got LOCKDS_REQ (%sLOCK) for DS:%s for session-id %" PRIu64
+ " from '%s'",
+ fe_msg->lockds_req->lock ? "" : "UN",
+ mgmt_ds_id2name(fe_msg->lockds_req->ds_id),
+ fe_msg->lockds_req->session_id, adapter->name);
mgmt_fe_session_handle_lockds_req_msg(
session, fe_msg->lockds_req);
break;
@@ -954,13 +979,12 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
session = mgmt_session_id2ctx(
fe_msg->setcfg_req->session_id);
session->adapter->setcfg_stats.set_cfg_count++;
- MGMTD_FE_ADAPTER_DBG(
- "Got SETCFG_REQ (%d Xpaths, Implicit:%c) on DS:%s for session-id %" PRIu64
- " from '%s'",
- (int)fe_msg->setcfg_req->n_data,
- fe_msg->setcfg_req->implicit_commit ? 'T' : 'F',
- mgmt_ds_id2name(fe_msg->setcfg_req->ds_id),
- fe_msg->setcfg_req->session_id, adapter->name);
+ __dbg("Got SETCFG_REQ (%d Xpaths, Implicit:%c) on DS:%s for session-id %" PRIu64
+ " from '%s'",
+ (int)fe_msg->setcfg_req->n_data,
+ fe_msg->setcfg_req->implicit_commit ? 'T' : 'F',
+ mgmt_ds_id2name(fe_msg->setcfg_req->ds_id),
+ fe_msg->setcfg_req->session_id, adapter->name);
mgmt_fe_session_handle_setcfg_req_msg(
session, fe_msg->setcfg_req);
@@ -968,31 +992,28 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ:
session = mgmt_session_id2ctx(
fe_msg->commcfg_req->session_id);
- MGMTD_FE_ADAPTER_DBG(
- "Got COMMCFG_REQ for src-DS:%s dst-DS:%s (Abort:%c) on session-id %" PRIu64
- " from '%s'",
- mgmt_ds_id2name(fe_msg->commcfg_req->src_ds_id),
- mgmt_ds_id2name(fe_msg->commcfg_req->dst_ds_id),
- fe_msg->commcfg_req->abort ? 'T' : 'F',
- fe_msg->commcfg_req->session_id, adapter->name);
+ __dbg("Got COMMCFG_REQ for src-DS:%s dst-DS:%s (Abort:%c) on session-id %" PRIu64
+ " from '%s'",
+ mgmt_ds_id2name(fe_msg->commcfg_req->src_ds_id),
+ mgmt_ds_id2name(fe_msg->commcfg_req->dst_ds_id),
+ fe_msg->commcfg_req->abort ? 'T' : 'F',
+ fe_msg->commcfg_req->session_id, adapter->name);
mgmt_fe_session_handle_commit_config_req_msg(
session, fe_msg->commcfg_req);
break;
case MGMTD__FE_MESSAGE__MESSAGE_GET_REQ:
session = mgmt_session_id2ctx(fe_msg->get_req->session_id);
- MGMTD_FE_ADAPTER_DBG("Got GET_REQ (iscfg %d) for DS:%s (xpaths: %d) on session-id %" PRIu64
- " from '%s'",
- (int)fe_msg->get_req->config,
- mgmt_ds_id2name(fe_msg->get_req->ds_id),
- (int)fe_msg->get_req->n_data,
- fe_msg->get_req->session_id, adapter->name);
+ __dbg("Got GET_REQ for DS:%s (xpaths: %d) on session-id %" PRIu64
+ " from '%s'",
+ mgmt_ds_id2name(fe_msg->get_req->ds_id),
+ (int)fe_msg->get_req->n_data, fe_msg->get_req->session_id,
+ adapter->name);
mgmt_fe_session_handle_get_req_msg(session, fe_msg->get_req);
break;
case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ:
case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ:
- MGMTD_FE_ADAPTER_ERR(
- "Got unhandled message of type %u from '%s'",
- fe_msg->message_case, adapter->name);
+ __log_err("Got unhandled message of type %u from '%s'",
+ fe_msg->message_case, adapter->name);
/*
* TODO: Add handling code in future.
*/
@@ -1020,25 +1041,265 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
return 0;
}
+/**
+ * Send result of get-tree request back to the FE client.
+ *
+ * Args:
+ * session: the session.
+ * req_id: the request ID.
+ * short_circuit_ok: if allowed to short circuit the message.
+ * result_format: LYD_FORMAT for the sent output.
+ * tree: the tree to send, can be NULL which will send an empty tree.
+ * partial_error: if an error occurred during gathering results.
+ *
+ * Return:
+ * Any error that occurs -- the message is likely not sent if non-zero.
+ */
+static int fe_adapter_send_tree_data(struct mgmt_fe_session_ctx *session,
+ uint64_t req_id, bool short_circuit_ok,
+ uint8_t result_type, uint32_t wd_options,
+ const struct lyd_node *tree,
+ int partial_error)
+
+{
+ struct mgmt_msg_tree_data *msg;
+ uint8_t **darrp = NULL;
+ int ret = 0;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_tree_data, 0,
+ MTYPE_MSG_NATIVE_TREE_DATA);
+ msg->refer_id = session->session_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_TREE_DATA;
+ msg->partial_error = partial_error;
+ msg->result_type = result_type;
+
+ darrp = mgmt_msg_native_get_darrp(msg);
+ ret = yang_print_tree_append(darrp, tree, result_type,
+ (wd_options | LYD_PRINT_WITHSIBLINGS));
+ if (ret != LY_SUCCESS) {
+ __log_err("Error building get-tree result for client %s session-id %" PRIu64
+ " req-id %" PRIu64 " scok %d result type %u",
+ session->adapter->name, session->session_id, req_id,
+ short_circuit_ok, result_type);
+ goto done;
+ }
+
+ __dbg("Sending get-tree result from adapter %s to session-id %" PRIu64
+ " req-id %" PRIu64 " scok %d result type %u len %u",
+ session->adapter->name, session->session_id, req_id,
+ short_circuit_ok, result_type, mgmt_msg_native_get_msg_len(msg));
+
+ ret = fe_adapter_send_native_msg(session->adapter, msg,
+ mgmt_msg_native_get_msg_len(msg),
+ short_circuit_ok);
+done:
+ mgmt_msg_native_free_msg(msg);
+
+ return ret;
+}
+
+/**
+ * fe_adapter_handle_get_data() - Handle a get-tree message from a FE client.
+ * @session: the client session.
+ * @msg_raw: the message data.
+ * @msg_len: the length of the message data.
+ */
+static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
+ void *__msg, size_t msg_len)
+{
+ struct mgmt_msg_get_data *msg = __msg;
+ struct lysc_node **snodes = NULL;
+ char *xpath_resolved = NULL;
+ uint64_t req_id = msg->req_id;
+ Mgmtd__DatastoreId ds_id;
+ uint64_t clients;
+ uint32_t wd_options;
+ bool simple_xpath;
+ LY_ERR err;
+ int ret;
+
+ __dbg("Received get-data request from client %s for session-id %" PRIu64
+ " req-id %" PRIu64,
+ session->adapter->name, session->session_id, msg->req_id);
+
+ if (!MGMT_MSG_VALIDATE_NUL_TERM(msg, msg_len)) {
+ fe_adapter_send_error(session, req_id, false, -EINVAL,
+ "Invalid message rcvd from session-id: %" PRIu64,
+ session->session_id);
+ goto done;
+ }
+
+ if (session->txn_id != MGMTD_TXN_ID_NONE) {
+ fe_adapter_send_error(session, req_id, false, -EINPROGRESS,
+ "Transaction in progress txn-id: %" PRIu64
+ " for session-id: %" PRIu64,
+ session->txn_id, session->session_id);
+ goto done;
+ }
+
+ switch (msg->defaults) {
+ case GET_DATA_DEFAULTS_EXPLICIT:
+ wd_options = LYD_PRINT_WD_EXPLICIT;
+ break;
+ case GET_DATA_DEFAULTS_TRIM:
+ wd_options = LYD_PRINT_WD_TRIM;
+ break;
+ case GET_DATA_DEFAULTS_ALL:
+ wd_options = LYD_PRINT_WD_ALL;
+ break;
+ case GET_DATA_DEFAULTS_ALL_ADD_TAG:
+ wd_options = LYD_PRINT_WD_IMPL_TAG;
+ break;
+ default:
+ fe_adapter_send_error(session, req_id, false, -EINVAL,
+ "Invalid defaults value %u for session-id: %" PRIu64,
+ msg->defaults, session->session_id);
+ goto done;
+ }
+
+ switch (msg->datastore) {
+ case MGMT_MSG_DATASTORE_CANDIDATE:
+ ds_id = MGMTD_DS_CANDIDATE;
+ break;
+ case MGMT_MSG_DATASTORE_RUNNING:
+ ds_id = MGMTD_DS_RUNNING;
+ break;
+ case MGMT_MSG_DATASTORE_OPERATIONAL:
+ ds_id = MGMTD_DS_OPERATIONAL;
+ break;
+ default:
+ fe_adapter_send_error(session, req_id, false, -EINVAL,
+ "Unsupported datastore %" PRIu8
+ " requested from session-id: %" PRIu64,
+ msg->datastore, session->session_id);
+ goto done;
+ }
+
+ err = yang_resolve_snode_xpath(ly_native_ctx, msg->xpath, &snodes,
+ &simple_xpath);
+ if (err) {
+ fe_adapter_send_error(session, req_id, false, -EINPROGRESS,
+ "XPath doesn't resolve for session-id: %" PRIu64,
+ session->session_id);
+ goto done;
+ }
+ darr_free(snodes);
+
+ clients = mgmt_be_interested_clients(msg->xpath, false);
+ if (!clients && !CHECK_FLAG(msg->flags, GET_DATA_FLAG_CONFIG)) {
+ __dbg("No backends provide xpath: %s for txn-id: %" PRIu64
+ " session-id: %" PRIu64,
+ msg->xpath, session->txn_id, session->session_id);
+
+ fe_adapter_send_tree_data(session, req_id, false,
+ msg->result_type, wd_options, NULL, 0);
+ goto done;
+ }
+
+ /* Start a SHOW Transaction */
+ session->txn_id = mgmt_create_txn(session->session_id,
+ MGMTD_TXN_TYPE_SHOW);
+ if (session->txn_id == MGMTD_SESSION_ID_NONE) {
+ fe_adapter_send_error(session, req_id, false, -EINPROGRESS,
+ "failed to create a 'show' txn");
+ goto done;
+ }
+
+ __dbg("Created new show txn-id: %" PRIu64 " for session-id: %" PRIu64,
+ session->txn_id, session->session_id);
+
+ /* Create a GET-TREE request under the transaction */
+ ret = mgmt_txn_send_get_tree_oper(session->txn_id, req_id, clients,
+ ds_id, msg->result_type, msg->flags,
+ wd_options, simple_xpath, msg->xpath);
+ if (ret) {
+ /* destroy the just created txn */
+ mgmt_destroy_txn(&session->txn_id);
+ fe_adapter_send_error(session, req_id, false, -EINPROGRESS,
+ "failed to create a 'show' txn");
+ }
+done:
+ darr_free(snodes);
+ darr_free(xpath_resolved);
+}
+
+/**
+ * Handle a native encoded message from the FE client.
+ */
+static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter,
+ struct mgmt_msg_header *msg,
+ size_t msg_len)
+{
+ struct mgmt_fe_session_ctx *session;
+
+ session = mgmt_session_id2ctx(msg->refer_id);
+ if (!session) {
+ __log_err("adapter %s: recv msg unknown session-id %" PRIu64,
+ adapter->name, msg->refer_id);
+ return;
+ }
+ assert(session->adapter == adapter);
+
+ switch (msg->code) {
+ case MGMT_MSG_CODE_GET_DATA:
+ fe_adapter_handle_get_data(session, msg, msg_len);
+ break;
+ default:
+ __log_err("unknown native message session-id %" PRIu64
+ " req-id %" PRIu64 " code %u to FE adapter %s",
+ msg->refer_id, msg->req_id, msg->code, adapter->name);
+ break;
+ }
+}
+
+
static void mgmt_fe_adapter_process_msg(uint8_t version, uint8_t *data,
size_t len, struct msg_conn *conn)
{
struct mgmt_fe_client_adapter *adapter = conn->user;
- Mgmtd__FeMessage *fe_msg = mgmtd__fe_message__unpack(NULL, len, data);
+ Mgmtd__FeMessage *fe_msg;
+
+ if (version == MGMT_MSG_VERSION_NATIVE) {
+ struct mgmt_msg_header *msg = (typeof(msg))data;
+ if (len >= sizeof(*msg))
+ fe_adapter_handle_native_msg(adapter, msg, len);
+ else
+ __log_err("native message to adapter %s too short %zu",
+ adapter->name, len);
+ return;
+ }
+
+ fe_msg = mgmtd__fe_message__unpack(NULL, len, data);
if (!fe_msg) {
- MGMTD_FE_ADAPTER_DBG(
- "Failed to decode %zu bytes for adapter: %s", len,
- adapter->name);
+ __dbg("Failed to decode %zu bytes for adapter: %s", len,
+ adapter->name);
return;
}
- MGMTD_FE_ADAPTER_DBG(
- "Decoded %zu bytes of message: %u from adapter: %s", len,
- fe_msg->message_case, adapter->name);
+ __dbg("Decoded %zu bytes of message: %u from adapter: %s", len,
+ fe_msg->message_case, adapter->name);
(void)mgmt_fe_adapter_handle_msg(adapter, fe_msg);
mgmtd__fe_message__free_unpacked(fe_msg, NULL);
}
+void mgmt_fe_adapter_send_notify(struct mgmt_msg_notify_data *msg, size_t msglen)
+{
+ struct mgmt_fe_client_adapter *adapter;
+ struct mgmt_fe_session_ctx *session;
+
+ assert(msg->refer_id == 0);
+
+ FOREACH_ADAPTER_IN_LIST (adapter) {
+ FOREACH_SESSION_IN_LIST (adapter, session) {
+ msg->refer_id = session->session_id;
+ (void)fe_adapter_send_native_msg(adapter, msg, msglen,
+ false);
+ }
+ }
+ msg->refer_id = 0;
+}
+
void mgmt_fe_adapter_lock(struct mgmt_fe_client_adapter *adapter)
{
adapter->refcount++;
@@ -1062,6 +1323,8 @@ extern void mgmt_fe_adapter_unlock(struct mgmt_fe_client_adapter **adapter)
*/
void mgmt_fe_adapter_init(struct event_loop *tm)
{
+ char server_path[MAXPATHLEN];
+
assert(!mgmt_loop);
mgmt_loop = tm;
@@ -1072,9 +1335,10 @@ void mgmt_fe_adapter_init(struct event_loop *tm)
hash_create(mgmt_fe_session_hash_key, mgmt_fe_session_hash_cmp,
"MGMT Frontend Sessions");
- if (msg_server_init(&mgmt_fe_server, MGMTD_FE_SERVER_PATH, tm,
- mgmt_fe_create_adapter, "frontend",
- &mgmt_debug_fe)) {
+ snprintf(server_path, sizeof(server_path), MGMTD_FE_SOCK_NAME);
+
+ if (msg_server_init(&mgmt_fe_server, server_path, tm,
+ mgmt_fe_create_adapter, "frontend", &mgmt_debug_fe)) {
zlog_err("cannot initialize frontend server");
exit(1);
}
@@ -1084,11 +1348,10 @@ static void mgmt_fe_abort_if_session(void *data)
{
struct mgmt_fe_session_ctx *session = data;
- MGMTD_FE_ADAPTER_ERR("found orphaned session id %" PRIu64
- " client id %" PRIu64 " adapter %s",
- session->session_id, session->client_id,
- session->adapter ? session->adapter->name
- : "NULL");
+ __log_err("found orphaned session id %" PRIu64 " client id %" PRIu64
+ " adapter %s",
+ session->session_id, session->client_id,
+ session->adapter ? session->adapter->name : "NULL");
abort();
}
@@ -1129,13 +1392,15 @@ struct msg_conn *mgmt_fe_create_adapter(int conn_fd, union sockunion *from)
adapter->conn = msg_server_conn_create(
mgmt_loop, conn_fd, mgmt_fe_adapter_notify_disconnect,
mgmt_fe_adapter_process_msg, MGMTD_FE_MAX_NUM_MSG_PROC,
- MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MSG_MAX_LEN,
+ MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MAX_MSG_LEN,
adapter, "FE-adapter");
+ adapter->conn->debug = DEBUG_MODE_CHECK(&mgmt_debug_fe,
+ DEBUG_MODE_ALL);
+
adapter->setcfg_stats.min_tm = ULONG_MAX;
adapter->cmt_stats.min_tm = ULONG_MAX;
- MGMTD_FE_ADAPTER_DBG("Added new MGMTD Frontend adapter '%s'",
- adapter->name);
+ __dbg("Added new MGMTD Frontend adapter '%s'", adapter->name);
}
return adapter->conn;
}
@@ -1151,10 +1416,9 @@ int mgmt_fe_send_set_cfg_reply(uint64_t session_id, uint64_t txn_id,
session = mgmt_session_id2ctx(session_id);
if (!session || session->cfg_txn_id != txn_id) {
if (session)
- MGMTD_FE_ADAPTER_ERR(
- "txn-id doesn't match, session txn-id is %" PRIu64
- " current txnid: %" PRIu64,
- session->cfg_txn_id, txn_id);
+ __log_err("txn-id doesn't match, session txn-id is %" PRIu64
+ " current txnid: %" PRIu64,
+ session->cfg_txn_id, txn_id);
return -1;
}
@@ -1198,8 +1462,56 @@ int mgmt_fe_send_get_reply(uint64_t session_id, uint64_t txn_id,
error_if_any);
}
-struct mgmt_setcfg_stats *
-mgmt_fe_get_session_setcfg_stats(uint64_t session_id)
+int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
+ uint64_t req_id, LYD_FORMAT result_type,
+ uint32_t wd_options,
+ const struct lyd_node *tree,
+ int partial_error, bool short_circuit_ok)
+{
+ struct mgmt_fe_session_ctx *session;
+ int ret;
+
+ session = mgmt_session_id2ctx(session_id);
+ if (!session || session->txn_id != txn_id)
+ return -1;
+
+ ret = fe_adapter_send_tree_data(session, req_id, short_circuit_ok,
+ result_type, wd_options, tree,
+ partial_error);
+
+ mgmt_destroy_txn(&session->txn_id);
+
+ return ret;
+}
+
+/**
+ * Send an error back to the FE client and cleanup any in-progress txn.
+ */
+int mgmt_fe_adapter_txn_error(uint64_t txn_id, uint64_t req_id,
+ bool short_circuit_ok, int16_t error,
+ const char *errstr)
+{
+ struct mgmt_fe_session_ctx *session;
+ int ret;
+
+ session = fe_adapter_session_by_txn_id(txn_id);
+ if (!session) {
+ __log_err("failed sending error for txn-id %" PRIu64
+ " session not found",
+ txn_id);
+ return -ENOENT;
+ }
+
+
+ ret = fe_adapter_send_error(session, req_id, false, error, "%s", errstr);
+
+ mgmt_destroy_txn(&session->txn_id);
+
+ return ret;
+}
+
+
+struct mgmt_setcfg_stats *mgmt_fe_get_session_setcfg_stats(uint64_t session_id)
{
struct mgmt_fe_session_ctx *session;