summaryrefslogtreecommitdiffstats
path: root/lib/mgmt_fe_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mgmt_fe_client.c')
-rw-r--r--lib/mgmt_fe_client.c320
1 files changed, 240 insertions, 80 deletions
diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c
index 7e42e1c..a107582 100644
--- a/lib/mgmt_fe_client.c
+++ b/lib/mgmt_fe_client.c
@@ -12,6 +12,7 @@
#include "libfrr.h"
#include "mgmt_fe_client.h"
#include "mgmt_msg.h"
+#include "mgmt_msg_native.h"
#include "mgmt_pb.h"
#include "network.h"
#include "stream.h"
@@ -47,8 +48,12 @@ struct mgmt_fe_client {
#define FOREACH_SESSION_IN_LIST(client, session) \
frr_each_safe (mgmt_sessions, &(client)->sessions, (session))
-struct debug mgmt_dbg_fe_client = {0, "Management frontend client operations"};
+struct debug mgmt_dbg_fe_client = {
+ .desc = "Management frontend client operations"
+};
+/* NOTE: only one client per proc for now. */
+static struct mgmt_fe_client *__fe_client;
static inline const char *dsid2name(Mgmtd__DatastoreId id)
{
@@ -74,14 +79,13 @@ mgmt_fe_find_session_by_client_id(struct mgmt_fe_client *client,
FOREACH_SESSION_IN_LIST (client, session) {
if (session->client_id == client_id) {
- MGMTD_FE_CLIENT_DBG("Found session-id %" PRIu64
- " using client-id %" PRIu64,
- session->session_id, client_id);
+ debug_fe_client("Found session-id %" PRIu64
+ " using client-id %" PRIu64,
+ session->session_id, client_id);
return session;
}
}
- MGMTD_FE_CLIENT_DBG("Session not found using client-id %" PRIu64,
- client_id);
+ debug_fe_client("Session not found using client-id %" PRIu64, client_id);
return NULL;
}
@@ -93,15 +97,14 @@ mgmt_fe_find_session_by_session_id(struct mgmt_fe_client *client,
FOREACH_SESSION_IN_LIST (client, session) {
if (session->session_id == session_id) {
- MGMTD_FE_CLIENT_DBG(
- "Found session of client-id %" PRIu64
- " using session-id %" PRIu64,
- session->client_id, session_id);
+ debug_fe_client("Found session of client-id %" PRIu64
+ " using session-id %" PRIu64,
+ session->client_id, session_id);
return session;
}
}
- MGMTD_FE_CLIENT_DBG("Session not found using session-id %" PRIu64,
- session_id);
+ debug_fe_client("Session not found using session-id %" PRIu64,
+ session_id);
return NULL;
}
@@ -128,8 +131,7 @@ static int mgmt_fe_send_register_req(struct mgmt_fe_client *client)
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ;
fe_msg.register_req = &rgstr_req;
- MGMTD_FE_CLIENT_DBG(
- "Sending REGISTER_REQ message to MGMTD Frontend server");
+ debug_fe_client("Sending REGISTER_REQ message to MGMTD Frontend server");
return mgmt_fe_client_send_msg(client, &fe_msg, true);
}
@@ -155,9 +157,8 @@ static int mgmt_fe_send_session_req(struct mgmt_fe_client *client,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ;
fe_msg.session_req = &sess_req;
- MGMTD_FE_CLIENT_DBG(
- "Sending SESSION_REQ %s message for client-id %" PRIu64,
- create ? "create" : "destroy", session->client_id);
+ debug_fe_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, true);
}
@@ -180,9 +181,8 @@ int mgmt_fe_send_lockds_req(struct mgmt_fe_client *client, uint64_t session_id,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ;
fe_msg.lockds_req = &lockds_req;
- MGMTD_FE_CLIENT_DBG(
- "Sending LOCKDS_REQ (%sLOCK) message for DS:%s session-id %" PRIu64,
- lock ? "" : "UN", dsid2name(ds_id), session_id);
+ debug_fe_client("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, scok);
@@ -210,10 +210,9 @@ int mgmt_fe_send_setcfg_req(struct mgmt_fe_client *client, uint64_t session_id,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ;
fe_msg.setcfg_req = &setcfg_req;
- MGMTD_FE_CLIENT_DBG(
- "Sending SET_CONFIG_REQ message for DS:%s session-id %" PRIu64
- " (#xpaths:%d)",
- dsid2name(ds_id), session_id, num_data_reqs);
+ debug_fe_client("Sending SET_CONFIG_REQ message for DS:%s session-id %" PRIu64
+ " (#xpaths:%d)",
+ dsid2name(ds_id), session_id, num_data_reqs);
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
@@ -240,9 +239,8 @@ int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client *client,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ;
fe_msg.commcfg_req = &commitcfg_req;
- MGMTD_FE_CLIENT_DBG(
- "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);
+ debug_fe_client("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);
}
@@ -268,10 +266,9 @@ int mgmt_fe_send_get_req(struct mgmt_fe_client *client, uint64_t session_id,
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GET_REQ;
fe_msg.get_req = &getcfg_req;
- MGMTD_FE_CLIENT_DBG("Sending GET_REQ (iscfg %d) message for DS:%s session-id %" PRIu64
- " (#xpaths:%d)",
- is_config, dsid2name(ds_id), session_id,
- num_data_reqs);
+ debug_fe_client("Sending GET_REQ (iscfg %d) message for DS:%s session-id %" PRIu64
+ " (#xpaths:%d)",
+ is_config, dsid2name(ds_id), session_id, num_data_reqs);
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
@@ -300,6 +297,39 @@ int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
+/*
+ * Send get-data request.
+ */
+int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
+ uint64_t session_id, uint64_t req_id,
+ uint8_t datastore, LYD_FORMAT result_type,
+ uint8_t flags, uint8_t defaults, const char *xpath)
+{
+ struct mgmt_msg_get_data *msg;
+ size_t xplen = strlen(xpath);
+ int ret;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_get_data, xplen + 1,
+ MTYPE_MSG_NATIVE_GET_DATA);
+ msg->refer_id = session_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_GET_DATA;
+ msg->result_type = result_type;
+ msg->flags = flags;
+ msg->defaults = defaults;
+ msg->datastore = datastore;
+ strlcpy(msg->xpath, xpath, xplen + 1);
+
+ debug_fe_client("Sending GET_DATA_REQ session-id %" PRIu64
+ " req-id %" PRIu64 " xpath: %s",
+ session_id, req_id, xpath);
+
+ ret = mgmt_msg_native_send_msg(&client->client.conn, msg, false);
+ mgmt_msg_native_free_msg(msg);
+ return ret;
+}
+
+
static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
Mgmtd__FeMessage *fe_msg)
{
@@ -313,30 +343,28 @@ static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY:
if (fe_msg->session_reply->create &&
fe_msg->session_reply->has_client_conn_id) {
- MGMTD_FE_CLIENT_DBG(
- "Got SESSION_REPLY (create) for client-id %" PRIu64
- " with session-id: %" PRIu64,
- fe_msg->session_reply->client_conn_id,
- fe_msg->session_reply->session_id);
+ debug_fe_client("Got SESSION_REPLY (create) for client-id %" PRIu64
+ " with session-id: %" PRIu64,
+ fe_msg->session_reply->client_conn_id,
+ fe_msg->session_reply->session_id);
session = mgmt_fe_find_session_by_client_id(
client, fe_msg->session_reply->client_conn_id);
if (session && fe_msg->session_reply->success) {
- MGMTD_FE_CLIENT_DBG(
- "Session Created for client-id %" PRIu64,
- fe_msg->session_reply->client_conn_id);
+ debug_fe_client("Session Created for client-id %" PRIu64,
+ fe_msg->session_reply
+ ->client_conn_id);
session->session_id =
fe_msg->session_reply->session_id;
} else {
- MGMTD_FE_CLIENT_ERR(
+ log_err_fe_client(
"Session Create failed for client-id %" PRIu64,
fe_msg->session_reply->client_conn_id);
}
} else if (!fe_msg->session_reply->create) {
- MGMTD_FE_CLIENT_DBG(
- "Got SESSION_REPLY (destroy) for session-id %" PRIu64,
- fe_msg->session_reply->session_id);
+ debug_fe_client("Got SESSION_REPLY (destroy) for session-id %" PRIu64,
+ fe_msg->session_reply->session_id);
session = mgmt_fe_find_session_by_session_id(
client, fe_msg->session_req->session_id);
@@ -353,8 +381,8 @@ static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
session->user_ctx);
break;
case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY:
- MGMTD_FE_CLIENT_DBG("Got LOCKDS_REPLY for session-id %" PRIu64,
- fe_msg->lockds_reply->session_id);
+ debug_fe_client("Got LOCKDS_REPLY for session-id %" PRIu64,
+ fe_msg->lockds_reply->session_id);
session = mgmt_fe_find_session_by_session_id(
client, fe_msg->lockds_reply->session_id);
@@ -370,8 +398,8 @@ static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
fe_msg->lockds_reply->error_if_any);
break;
case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY:
- MGMTD_FE_CLIENT_DBG("Got SETCFG_REPLY for session-id %" PRIu64,
- fe_msg->setcfg_reply->session_id);
+ debug_fe_client("Got SETCFG_REPLY for session-id %" PRIu64,
+ fe_msg->setcfg_reply->session_id);
session = mgmt_fe_find_session_by_session_id(
client, fe_msg->setcfg_reply->session_id);
@@ -388,8 +416,8 @@ static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
fe_msg->setcfg_reply->error_if_any);
break;
case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY:
- MGMTD_FE_CLIENT_DBG("Got COMMCFG_REPLY for session-id %" PRIu64,
- fe_msg->commcfg_reply->session_id);
+ debug_fe_client("Got COMMCFG_REPLY for session-id %" PRIu64,
+ fe_msg->commcfg_reply->session_id);
session = mgmt_fe_find_session_by_session_id(
client, fe_msg->commcfg_reply->session_id);
@@ -408,8 +436,8 @@ static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
fe_msg->commcfg_reply->error_if_any);
break;
case MGMTD__FE_MESSAGE__MESSAGE_GET_REPLY:
- MGMTD_FE_CLIENT_DBG("Got GET_REPLY for session-id %" PRIu64,
- fe_msg->get_reply->session_id);
+ debug_fe_client("Got GET_REPLY for session-id %" PRIu64,
+ fe_msg->get_reply->session_id);
session =
mgmt_fe_find_session_by_session_id(client,
@@ -465,6 +493,110 @@ static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
return 0;
}
+/*
+ * Handle a native encoded message
+ */
+static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
+ struct mgmt_msg_header *msg,
+ size_t msg_len)
+{
+ struct mgmt_fe_client_session *session = NULL;
+ struct mgmt_msg_notify_data *notify_msg;
+ struct mgmt_msg_tree_data *tree_msg;
+ struct mgmt_msg_error *err_msg;
+ const char *data = NULL;
+ size_t dlen;
+
+ debug_fe_client("Got native message for session-id %" PRIu64,
+ msg->refer_id);
+
+ session = mgmt_fe_find_session_by_session_id(client, msg->refer_id);
+ if (!session || !session->client) {
+ log_err_fe_client("No session for received native msg session-id %" PRIu64,
+ msg->refer_id);
+ return;
+ }
+
+ switch (msg->code) {
+ case MGMT_MSG_CODE_ERROR:
+ if (!session->client->cbs.error_notify)
+ return;
+
+ err_msg = (typeof(err_msg))msg;
+ if (!MGMT_MSG_VALIDATE_NUL_TERM(err_msg, msg_len)) {
+ log_err_fe_client("Corrupt error msg recv");
+ return;
+ }
+ session->client->cbs.error_notify(client, client->user_data,
+ session->client_id,
+ msg->refer_id,
+ session->user_ctx,
+ msg->req_id, err_msg->error,
+ err_msg->errstr);
+ break;
+ case MGMT_MSG_CODE_TREE_DATA:
+ if (!session->client->cbs.get_tree_notify)
+ return;
+
+ tree_msg = (typeof(tree_msg))msg;
+ if (msg_len < sizeof(*tree_msg)) {
+ log_err_fe_client("Corrupt tree-data msg recv");
+ return;
+ }
+ session->client->cbs.get_tree_notify(client, client->user_data,
+ session->client_id,
+ msg->refer_id,
+ session->user_ctx,
+ msg->req_id,
+ MGMTD_DS_OPERATIONAL,
+ tree_msg->result_type,
+ tree_msg->result,
+ msg_len - sizeof(*tree_msg),
+ tree_msg->partial_error);
+ break;
+ case MGMT_MSG_CODE_NOTIFY:
+ if (!session->client->cbs.async_notification)
+ return;
+
+ notify_msg = (typeof(notify_msg))msg;
+ if (msg_len < sizeof(*notify_msg)) {
+ log_err_fe_client("Corrupt notify-data msg recv");
+ return;
+ }
+
+ data = mgmt_msg_native_data_decode(notify_msg, msg_len);
+ if (!data) {
+ log_err_fe_client("Corrupt error msg recv");
+ return;
+ }
+ dlen = mgmt_msg_native_data_len_decode(notify_msg, msg_len);
+ if (notify_msg->result_type != LYD_JSON)
+ data = yang_convert_lyd_format(data, dlen,
+ notify_msg->result_type,
+ LYD_JSON, true);
+ if (!data) {
+ log_err_fe_client("Can't convert format %d to JSON",
+ notify_msg->result_type);
+ return;
+ }
+
+ session->client->cbs.async_notification(client,
+ client->user_data,
+ session->client_id,
+ msg->refer_id,
+ session->user_ctx, data);
+
+ if (notify_msg->result_type != LYD_JSON)
+ darr_free(data);
+ break;
+ default:
+ log_err_fe_client("unknown native message session-id %" PRIu64
+ " req-id %" PRIu64 " code %u",
+ msg->refer_id, msg->req_id, msg->code);
+ break;
+ }
+}
+
static void mgmt_fe_client_process_msg(uint8_t version, uint8_t *data,
size_t len, struct msg_conn *conn)
{
@@ -475,15 +607,24 @@ static void mgmt_fe_client_process_msg(uint8_t version, uint8_t *data,
msg_client = container_of(conn, struct msg_client, conn);
client = container_of(msg_client, struct mgmt_fe_client, client);
+ if (version == MGMT_MSG_VERSION_NATIVE) {
+ struct mgmt_msg_header *msg = (typeof(msg))data;
+
+ if (len >= sizeof(*msg))
+ fe_client_handle_native_msg(client, msg, len);
+ else
+ log_err_fe_client("native message to FE client %s too short %zu",
+ client->name, len);
+ return;
+ }
+
fe_msg = mgmtd__fe_message__unpack(NULL, len, data);
if (!fe_msg) {
- MGMTD_FE_CLIENT_DBG("Failed to decode %zu bytes from server.",
- len);
+ debug_fe_client("Failed to decode %zu bytes from server.", len);
return;
}
- MGMTD_FE_CLIENT_DBG(
- "Decoded %zu bytes of message(msg: %u/%u) from server", len,
- fe_msg->message_case, fe_msg->message_case);
+ debug_fe_client("Decoded %zu bytes of message(msg: %u/%u) from server",
+ len, fe_msg->message_case, fe_msg->message_case);
(void)mgmt_fe_client_handle_msg(client, fe_msg);
mgmtd__fe_message__free_unpacked(fe_msg, NULL);
}
@@ -504,7 +645,7 @@ static int _notify_connect_disconnect(struct msg_client *msg_client,
/* Walk list of sessions for this FE client deleting them */
if (!connected && mgmt_sessions_count(&client->sessions)) {
- MGMTD_FE_CLIENT_DBG("Cleaning up existing sessions");
+ debug_fe_client("Cleaning up existing sessions");
FOREACH_SESSION_IN_LIST (client, session) {
assert(session->client);
@@ -543,6 +684,16 @@ static int mgmt_fe_client_notify_disconnect(struct msg_conn *conn)
return _notify_connect_disconnect(client, false);
}
+static void mgmt_debug_client_fe_set(uint32_t mode, bool set)
+{
+ DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, mode, set);
+
+ if (!__fe_client)
+ return;
+
+ __fe_client->client.conn.debug = DEBUG_MODE_CHECK(&mgmt_dbg_fe_client,
+ DEBUG_MODE_ALL);
+}
DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd,
"[no] debug mgmt client frontend",
@@ -550,18 +701,11 @@ DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd,
"client\n"
"frontend\n")
{
- uint32_t mode = DEBUG_NODE2MODE(vty->node);
-
- DEBUG_MODE_SET(&mgmt_dbg_fe_client, mode, !no);
+ mgmt_debug_client_fe_set(DEBUG_NODE2MODE(vty->node), !no);
return CMD_SUCCESS;
}
-static void mgmt_debug_client_fe_set_all(uint32_t flags, bool set)
-{
- DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, flags, set);
-}
-
static int mgmt_debug_fe_client_config_write(struct vty *vty)
{
if (DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_CONF))
@@ -572,16 +716,17 @@ static int mgmt_debug_fe_client_config_write(struct vty *vty)
void mgmt_debug_fe_client_show_debug(struct vty *vty)
{
- if (MGMTD_DBG_FE_CLIENT_CHECK())
+ if (debug_check_fe_client())
vty_out(vty, "debug mgmt client frontend\n");
}
static struct debug_callbacks mgmt_dbg_fe_client_cbs = {
- .debug_set_all = mgmt_debug_client_fe_set_all};
+ .debug_set_all = mgmt_debug_client_fe_set
+};
static struct cmd_node mgmt_dbg_node = {
- .name = "mgmt client frontend",
- .node = DEBUG_NODE,
+ .name = "debug mgmt client frontend",
+ .node = MGMT_FE_DEBUG_NODE,
.prompt = "",
.config_write = mgmt_debug_fe_client_config_write,
};
@@ -594,8 +739,14 @@ struct mgmt_fe_client *mgmt_fe_client_create(const char *client_name,
uintptr_t user_data,
struct event_loop *event_loop)
{
- struct mgmt_fe_client *client =
- XCALLOC(MTYPE_MGMTD_FE_CLIENT, sizeof(*client));
+ struct mgmt_fe_client *client;
+ char server_path[MAXPATHLEN];
+
+ if (__fe_client)
+ return NULL;
+
+ client = XCALLOC(MTYPE_MGMTD_FE_CLIENT, sizeof(*client));
+ __fe_client = client;
client->name = XSTRDUP(MTYPE_MGMTD_FE_CLIENT_NAME, client_name);
client->user_data = user_data;
@@ -604,14 +755,16 @@ struct mgmt_fe_client *mgmt_fe_client_create(const char *client_name,
mgmt_sessions_init(&client->sessions);
- msg_client_init(&client->client, event_loop, MGMTD_FE_SERVER_PATH,
+ snprintf(server_path, sizeof(server_path), MGMTD_FE_SOCK_NAME);
+
+ msg_client_init(&client->client, event_loop, server_path,
mgmt_fe_client_notify_connect,
mgmt_fe_client_notify_disconnect,
mgmt_fe_client_process_msg, MGMTD_FE_MAX_NUM_MSG_PROC,
- MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MSG_MAX_LEN, true,
- "FE-client", MGMTD_DBG_FE_CLIENT_CHECK());
+ MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MAX_MSG_LEN, true,
+ "FE-client", debug_check_fe_client());
- MGMTD_FE_CLIENT_DBG("Initialized client '%s'", client_name);
+ debug_fe_client("Initialized client '%s'", client_name);
return client;
}
@@ -634,6 +787,11 @@ bool mgmt_fe_client_current_msg_short_circuit(struct mgmt_fe_client *client)
return client->client.conn.is_short_circuit;
}
+const char *mgmt_fe_client_name(struct mgmt_fe_client *client)
+{
+ return client->name;
+}
+
/*
* Create a new Session for a Frontend Client connection.
*/
@@ -675,9 +833,8 @@ enum mgmt_result mgmt_fe_destroy_client_session(struct mgmt_fe_client *client,
if (session->session_id &&
mgmt_fe_send_session_req(client, session, false) != 0)
- MGMTD_FE_CLIENT_ERR(
- "Failed to send session destroy request for the session-id %" PRIu64,
- session->session_id);
+ log_err_fe_client("Failed to send session destroy request for the session-id %" PRIu64,
+ session->session_id);
mgmt_sessions_del(&client->sessions, session);
XFREE(MTYPE_MGMTD_FE_SESSION, session);
@@ -692,8 +849,9 @@ void mgmt_fe_client_destroy(struct mgmt_fe_client *client)
{
struct mgmt_fe_client_session *session;
- MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'",
- client->name);
+ assert(client == __fe_client);
+
+ debug_fe_client("Destroying MGMTD Frontend Client '%s'", client->name);
FOREACH_SESSION_IN_LIST (client, session)
mgmt_fe_destroy_client_session(client, session->client_id);
@@ -702,4 +860,6 @@ void mgmt_fe_client_destroy(struct mgmt_fe_client *client)
XFREE(MTYPE_MGMTD_FE_CLIENT_NAME, client->name);
XFREE(MTYPE_MGMTD_FE_CLIENT, client);
+
+ __fe_client = NULL;
}