mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
lib: add native RPC processing to mgmt frontend client
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
parent
cb6c182852
commit
a94f74bc2e
|
@ -360,6 +360,33 @@ int mgmt_fe_send_edit_req(struct mgmt_fe_client *client, uint64_t session_id,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int mgmt_fe_send_rpc_req(struct mgmt_fe_client *client, uint64_t session_id,
|
||||
uint64_t req_id, LYD_FORMAT request_type,
|
||||
const char *xpath, const char *data)
|
||||
{
|
||||
struct mgmt_msg_rpc *msg;
|
||||
int ret;
|
||||
|
||||
msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc, 0,
|
||||
MTYPE_MSG_NATIVE_RPC);
|
||||
msg->refer_id = session_id;
|
||||
msg->req_id = req_id;
|
||||
msg->code = MGMT_MSG_CODE_RPC;
|
||||
msg->request_type = request_type;
|
||||
|
||||
mgmt_msg_native_xpath_encode(msg, xpath);
|
||||
if (data)
|
||||
mgmt_msg_native_append(msg, data, strlen(data) + 1);
|
||||
|
||||
debug_fe_client("Sending RPC_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)
|
||||
{
|
||||
|
@ -534,6 +561,7 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
|
|||
struct mgmt_msg_notify_data *notify_msg;
|
||||
struct mgmt_msg_tree_data *tree_msg;
|
||||
struct mgmt_msg_edit_reply *edit_msg;
|
||||
struct mgmt_msg_rpc_reply *rpc_msg;
|
||||
struct mgmt_msg_error *err_msg;
|
||||
const char *xpath = NULL;
|
||||
const char *data = NULL;
|
||||
|
@ -608,6 +636,23 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
|
|||
session->user_ctx, msg->req_id,
|
||||
xpath);
|
||||
break;
|
||||
case MGMT_MSG_CODE_RPC_REPLY:
|
||||
if (!session->client->cbs.rpc_notify)
|
||||
return;
|
||||
|
||||
rpc_msg = (typeof(rpc_msg))msg;
|
||||
if (msg_len < sizeof(*rpc_msg)) {
|
||||
log_err_fe_client("Corrupt rpc-reply msg recv");
|
||||
return;
|
||||
}
|
||||
dlen = msg_len - sizeof(*rpc_msg);
|
||||
|
||||
session->client->cbs.rpc_notify(client, client->user_data,
|
||||
session->client_id,
|
||||
msg->refer_id,
|
||||
session->user_ctx, msg->req_id,
|
||||
dlen ? rpc_msg->data : NULL);
|
||||
break;
|
||||
case MGMT_MSG_CODE_NOTIFY:
|
||||
if (!session->client->cbs.async_notification)
|
||||
return;
|
||||
|
|
|
@ -120,6 +120,12 @@ struct mgmt_fe_client_cbs {
|
|||
uintptr_t session_ctx, uint64_t req_id,
|
||||
const char *xpath);
|
||||
|
||||
/* Called when RPC result is returned */
|
||||
int (*rpc_notify)(struct mgmt_fe_client *client, uintptr_t user_data,
|
||||
uint64_t client_id, uint64_t session_id,
|
||||
uintptr_t session_ctx, uint64_t req_id,
|
||||
const char *result);
|
||||
|
||||
/* Called with asynchronous notifications from backends */
|
||||
int (*async_notification)(struct mgmt_fe_client *client,
|
||||
uintptr_t user_data, uint64_t client_id,
|
||||
|
@ -454,6 +460,35 @@ extern int mgmt_fe_send_edit_req(struct mgmt_fe_client *client,
|
|||
uint8_t flags, uint8_t operation,
|
||||
const char *xpath, const char *data);
|
||||
|
||||
/*
|
||||
* Send RPC request to MGMTD daemon.
|
||||
*
|
||||
* client
|
||||
* Client object.
|
||||
*
|
||||
* session_id
|
||||
* Client session ID.
|
||||
*
|
||||
* req_id
|
||||
* Client request ID.
|
||||
*
|
||||
* result_type
|
||||
* The LYD_FORMAT of the result.
|
||||
*
|
||||
* xpath
|
||||
* the xpath of the RPC.
|
||||
*
|
||||
* data
|
||||
* the data tree.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, otherwise msg_conn_send_msg() return values.
|
||||
*/
|
||||
extern int mgmt_fe_send_rpc_req(struct mgmt_fe_client *client,
|
||||
uint64_t session_id, uint64_t req_id,
|
||||
LYD_FORMAT request_type, const char *xpath,
|
||||
const char *data);
|
||||
|
||||
/*
|
||||
* Destroy library and cleanup everything.
|
||||
*/
|
||||
|
|
|
@ -322,6 +322,22 @@ int nb_cli_rpc(struct vty *vty, const char *xpath, struct lyd_node **output_p)
|
|||
assert(err == LY_SUCCESS);
|
||||
}
|
||||
|
||||
if (vty_mgmt_fe_enabled()) {
|
||||
char *data = NULL;
|
||||
|
||||
err = lyd_print_mem(&data, input, LYD_JSON, LYD_PRINT_SHRINK);
|
||||
assert(err == LY_SUCCESS);
|
||||
|
||||
ret = vty_mgmt_send_rpc_req(vty, LYD_JSON, xpath, data);
|
||||
|
||||
free(data);
|
||||
lyd_free_all(input);
|
||||
|
||||
if (ret < 0)
|
||||
return CMD_WARNING;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* validate input tree to create implicit defaults */
|
||||
err = lyd_validate_op(input, NULL, LYD_TYPE_RPC_YANG, NULL);
|
||||
assert(err == LY_SUCCESS);
|
||||
|
|
40
lib/vty.c
40
lib/vty.c
|
@ -3843,6 +3843,26 @@ static int vty_mgmt_edit_result_notified(struct mgmt_fe_client *client,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vty_mgmt_rpc_result_notified(struct mgmt_fe_client *client,
|
||||
uintptr_t user_data, uint64_t client_id,
|
||||
uint64_t session_id,
|
||||
uintptr_t session_ctx, uint64_t req_id,
|
||||
const char *result)
|
||||
{
|
||||
struct vty *vty = (struct vty *)session_ctx;
|
||||
|
||||
debug_fe_client("RPC request for client 0x%" PRIx64 " req-id %" PRIu64
|
||||
" was successful",
|
||||
client_id, req_id);
|
||||
|
||||
if (result)
|
||||
vty_out(vty, "%s\n", result);
|
||||
|
||||
vty_mgmt_resume_response(vty, CMD_SUCCESS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vty_mgmt_error_notified(struct mgmt_fe_client *client,
|
||||
uintptr_t user_data, uint64_t client_id,
|
||||
uint64_t session_id, uintptr_t session_ctx,
|
||||
|
@ -3885,6 +3905,7 @@ static struct mgmt_fe_client_cbs mgmt_cbs = {
|
|||
.get_data_notify = vty_mgmt_get_data_result_notified,
|
||||
.get_tree_notify = vty_mgmt_get_tree_result_notified,
|
||||
.edit_notify = vty_mgmt_edit_result_notified,
|
||||
.rpc_notify = vty_mgmt_rpc_result_notified,
|
||||
.error_notify = vty_mgmt_error_notified,
|
||||
|
||||
};
|
||||
|
@ -4162,6 +4183,25 @@ int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int vty_mgmt_send_rpc_req(struct vty *vty, LYD_FORMAT request_type,
|
||||
const char *xpath, const char *data)
|
||||
{
|
||||
vty->mgmt_req_id++;
|
||||
|
||||
if (mgmt_fe_send_rpc_req(mgmt_fe_client, vty->mgmt_session_id,
|
||||
vty->mgmt_req_id, request_type, xpath, data)) {
|
||||
zlog_err("Failed to send RPC to MGMTD session-id: %" PRIu64
|
||||
" req-id %" PRIu64 ".",
|
||||
vty->mgmt_session_id, vty->mgmt_req_id);
|
||||
vty_out(vty, "Failed to send RPC to MGMTD!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vty->mgmt_req_pending_cmd = "MESSAGE_RPC_REQ";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Install vty's own commands like `who' command. */
|
||||
void vty_init(struct event_loop *master_thread, bool do_command_logging)
|
||||
{
|
||||
|
|
|
@ -427,6 +427,8 @@ extern int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore,
|
|||
LYD_FORMAT request_type, uint8_t flags,
|
||||
uint8_t operation, const char *xpath,
|
||||
const char *data);
|
||||
extern int vty_mgmt_send_rpc_req(struct vty *vty, LYD_FORMAT request_type,
|
||||
const char *xpath, const char *data);
|
||||
extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id,
|
||||
bool lock, bool scok);
|
||||
extern void vty_mgmt_resume_response(struct vty *vty, int ret);
|
||||
|
|
|
@ -296,6 +296,21 @@ DEFPY(mgmt_edit, mgmt_edit_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY(mgmt_rpc, mgmt_rpc_cmd,
|
||||
"mgmt rpc XPATH [json|xml]$fmt [DATA]",
|
||||
MGMTD_STR
|
||||
"Invoke RPC\n"
|
||||
"XPath expression specifying the YANG data path\n"
|
||||
"JSON input format (default)\n"
|
||||
"XML input format\n"
|
||||
"Input data tree\n")
|
||||
{
|
||||
LYD_FORMAT format = (fmt && fmt[0] == 'x') ? LYD_XML : LYD_JSON;
|
||||
|
||||
vty_mgmt_send_rpc_req(vty, format, xpath, data);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd,
|
||||
"show mgmt get-config [candidate|operational|running]$dsname WORD$path",
|
||||
SHOW_STR MGMTD_STR
|
||||
|
@ -702,6 +717,7 @@ void mgmt_vty_init(void)
|
|||
install_element(CONFIG_NODE, &mgmt_remove_config_data_cmd);
|
||||
install_element(CONFIG_NODE, &mgmt_replace_config_data_cmd);
|
||||
install_element(CONFIG_NODE, &mgmt_edit_cmd);
|
||||
install_element(CONFIG_NODE, &mgmt_rpc_cmd);
|
||||
install_element(CONFIG_NODE, &mgmt_load_config_cmd);
|
||||
install_element(CONFIG_NODE, &mgmt_save_config_cmd);
|
||||
install_element(CONFIG_NODE, &mgmt_rollback_cmd);
|
||||
|
|
Loading…
Reference in a new issue