diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c index cc33b9d2d6a2..73fcbe3ff207 100644 --- a/lib/mgmt_fe_client.c +++ b/lib/mgmt_fe_client.c @@ -311,7 +311,7 @@ int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client, int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client, uint64_t session_id, uint64_t req_id, LYD_FORMAT result_type, enum mgmt_msg_get_data_content content, - const char *xpath) + bool exact, const char *xpath) { struct mgmt_msg_get_data *msg; size_t xplen = strlen(xpath); @@ -324,6 +324,7 @@ int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client, uint64_t session_id msg->code = MGMT_MSG_CODE_GET_DATA; msg->result_type = result_type; msg->content = content; + msg->exact = exact; strlcpy(msg->xpath, xpath, xplen + 1); MGMTD_FE_CLIENT_DBG("Sending GET_DATA_REQ session-id %" PRIu64 diff --git a/lib/mgmt_fe_client.h b/lib/mgmt_fe_client.h index 3e31f2bed321..5c579b1f8974 100644 --- a/lib/mgmt_fe_client.h +++ b/lib/mgmt_fe_client.h @@ -385,6 +385,9 @@ extern int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client, * content * The content type of the result. * + * exact + * Return the exact node requested instead of the full tree. + * * xpath * the xpath to get. * @@ -395,7 +398,7 @@ extern int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client, uint64_t session_id, uint64_t req_id, LYD_FORMAT result_type, enum mgmt_msg_get_data_content content, - const char *xpath); + bool exact, const char *xpath); /* * Destroy library and cleanup everything. diff --git a/lib/mgmt_msg_native.h b/lib/mgmt_msg_native.h index b6759b811c97..be18e5caca6c 100644 --- a/lib/mgmt_msg_native.h +++ b/lib/mgmt_msg_native.h @@ -250,13 +250,15 @@ enum mgmt_msg_get_data_content { * * @result_type: ``LYD_FORMAT`` for the returned result. * @content: ``enum mgmt_msg_get_data_content``. + * @exact: return the exact node requested instead of the full tree. * @xpath: the query for the data to return. */ struct mgmt_msg_get_data { struct mgmt_msg_header; uint8_t result_type; uint8_t content; - uint8_t resv2[6]; + uint8_t exact; + uint8_t resv2[5]; alignas(8) char xpath[]; }; diff --git a/lib/vty.c b/lib/vty.c index 4cf61d6633b5..055479741c69 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -4107,7 +4107,7 @@ int vty_mgmt_send_get_req(struct vty *vty, bool is_config, int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type, enum mgmt_msg_get_data_content content, - const char *xpath) + bool exact, const char *xpath) { LYD_FORMAT intern_format = result_type; @@ -4115,7 +4115,7 @@ int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type, if (mgmt_fe_send_get_data_req(mgmt_fe_client, vty->mgmt_session_id, vty->mgmt_req_id, intern_format, content, - xpath)) { + exact, xpath)) { zlog_err("Failed to send GET-DATA to MGMTD session-id: %" PRIu64 " req-id %" PRIu64 ".", vty->mgmt_session_id, vty->mgmt_req_id); diff --git a/lib/vty.h b/lib/vty.h index 7162a6b7788b..f68f7c786b2a 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -422,7 +422,7 @@ extern int vty_mgmt_send_get_req(struct vty *vty, bool is_config, const char **xpath_list, int num_req); extern int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type, enum mgmt_msg_get_data_content content, - const char *xpath); + bool exact, const char *xpath); 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); diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c index 1605a2fd6f5f..06a27f60c667 100644 --- a/mgmtd/mgmt_fe_adapter.c +++ b/mgmtd/mgmt_fe_adapter.c @@ -1208,7 +1208,7 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session, /* Create a GET-TREE request under the transaction */ ret = mgmt_txn_send_get_tree_oper(session->txn_id, req_id, clients, msg->result_type, msg->content, - simple_xpath, msg->xpath); + msg->exact, simple_xpath, msg->xpath); if (ret) { /* destroy the just created txn */ mgmt_destroy_txn(&session->txn_id); diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c index c1010e197cc4..178c2bc8720d 100644 --- a/mgmtd/mgmt_txn.c +++ b/mgmtd/mgmt_txn.c @@ -176,6 +176,7 @@ struct txn_req_get_tree { uint64_t recv_clients; /* Bitmask of clients recv reply from */ int32_t partial_error; /* an error while gather results */ uint8_t result_type; /* LYD_FORMAT for results */ + uint8_t exact; /* if exact node is requested */ uint8_t simple_xpath; /* if xpath is simple */ struct lyd_node *client_results; /* result tree from clients */ }; @@ -1258,6 +1259,7 @@ static int txn_get_tree_data_done(struct mgmt_txn_ctx *txn, { struct txn_req_get_tree *get_tree = txn_req->req.get_tree; uint64_t req_id = txn_req->req_id; + struct lyd_node *result; int ret = NB_OK; /* cancel timer and send reply onward */ @@ -1272,12 +1274,17 @@ static int txn_get_tree_data_done(struct mgmt_txn_ctx *txn, ret = NB_ERR; } + result = get_tree->client_results; + + if (ret == NB_OK && result && get_tree->exact) + result = yang_dnode_get(result, get_tree->xpath); + if (ret == NB_OK) ret = mgmt_fe_adapter_send_tree_data(txn->session_id, txn->txn_id, txn_req->req_id, get_tree->result_type, - get_tree->client_results, + result, get_tree->partial_error, false); @@ -2365,7 +2372,7 @@ int mgmt_txn_send_get_req(uint64_t txn_id, uint64_t req_id, int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id, uint64_t clients, LYD_FORMAT result_type, enum mgmt_msg_get_data_content content, - bool simple_xpath, const char *xpath) + bool exact, bool simple_xpath, const char *xpath) { struct mgmt_msg_get_tree *msg; struct mgmt_txn_ctx *txn; @@ -2383,6 +2390,7 @@ int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id, txn_req = mgmt_txn_req_alloc(txn, req_id, MGMTD_TXN_PROC_GETTREE); get_tree = txn_req->req.get_tree; get_tree->result_type = result_type; + get_tree->exact = exact; get_tree->simple_xpath = simple_xpath; get_tree->xpath = XSTRDUP(MTYPE_MGMTD_XPATH, xpath); diff --git a/mgmtd/mgmt_txn.h b/mgmtd/mgmt_txn.h index b4a15813e886..0bf1c836704d 100644 --- a/mgmtd/mgmt_txn.h +++ b/mgmtd/mgmt_txn.h @@ -204,6 +204,7 @@ extern int mgmt_txn_send_get_req(uint64_t txn_id, uint64_t req_id, * clients: Bitmask of clients to send get-tree to. * result_type: LYD_FORMAT result format. * content: The content type to get. + * exact: request the exact node instead of the full tree. * simple_xpath: true if xpath is simple (only key predicates). * xpath: The xpath to get the tree from. * @@ -213,7 +214,8 @@ extern int mgmt_txn_send_get_req(uint64_t txn_id, uint64_t req_id, extern int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id, uint64_t clients, LYD_FORMAT result_type, enum mgmt_msg_get_data_content content, - bool simple_xpath, const char *xpath); + bool exact, bool simple_xpath, + const char *xpath); /* * Notifiy backend adapter on connection. diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index fe8bd8b9654e..fe0d3ea16aae 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -251,13 +251,14 @@ DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd, } DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd, - "show mgmt get-data WORD$path [with-config|only-config]$cont [json|xml]$fmt", + "show mgmt get-data WORD$path [with-config|only-config]$cont [exact]$exact [json|xml]$fmt", SHOW_STR MGMTD_STR "Get a data from the operational datastore\n" "XPath expression specifying the YANG data root\n" "Include \"config true\" data\n" "Get only \"config true\" data\n" + "Get exact node instead of the whole data tree\n" "JSON output format\n" "XML output format\n") { @@ -282,7 +283,7 @@ DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd, path = xpath; } - vty_mgmt_send_get_data_req(vty, format, content, path); + vty_mgmt_send_get_data_req(vty, format, content, exact ? true : false, path); if (xpath) XFREE(MTYPE_TMP, xpath);