diff options
Diffstat (limited to 'lib/mgmt_fe_client.c')
-rw-r--r-- | lib/mgmt_fe_client.c | 320 |
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; } |