]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib, mgmtd: add ability to set content type in get-data request
authorIgor Ryzhov <iryzhov@nfware.com>
Sat, 13 Jan 2024 20:51:45 +0000 (22:51 +0200)
committerIgor Ryzhov <iryzhov@nfware.com>
Mon, 15 Jan 2024 08:27:33 +0000 (10:27 +0200)
Like in RESTCONF GET request and NETCONF get-data request, make it
possible to request state-only, config-only, or all data.

Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
lib/mgmt_fe_client.c
lib/mgmt_fe_client.h
lib/mgmt_msg_native.h
lib/vty.c
lib/vty.h
mgmtd/mgmt_fe_adapter.c
mgmtd/mgmt_txn.c
mgmtd/mgmt_txn.h
mgmtd/mgmt_vty.c

index 16559c61031affa091014f979b41f990dc42d6a0..57ac071ecf5a74529bf8058ebe0bb7b737efabbf 100644 (file)
@@ -308,9 +308,9 @@ int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
 /*
  * Send get-data request.
  */
-int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
-                             uint64_t session_id, uint64_t req_id,
-                             LYD_FORMAT result_type, const char *xpath)
+int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client, uint64_t session_id,
+                             uint64_t req_id, LYD_FORMAT result_type,
+                             uint8_t flags, const char *xpath)
 {
        struct mgmt_msg_get_data *msg;
        size_t xplen = strlen(xpath);
@@ -322,6 +322,7 @@ int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
        msg->req_id = req_id;
        msg->code = MGMT_MSG_CODE_GET_DATA;
        msg->result_type = result_type;
+       msg->flags = flags;
        strlcpy(msg->xpath, xpath, xplen + 1);
 
        MGMTD_FE_CLIENT_DBG("Sending GET_DATA_REQ session-id %" PRIu64
index 95e73ca5947880271ca70ee9b6d08c38861c89ec..3abe29b1cf398f270716951d10d08f7dd09c8046 100644 (file)
@@ -15,6 +15,7 @@ extern "C" {
 #include "mgmt_pb.h"
 #include "frrevent.h"
 #include "mgmt_defines.h"
+#include "mgmt_msg_native.h"
 
 /***************************************************************
  * Macros
@@ -381,6 +382,9 @@ extern int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
  * result_type
  *    The LYD_FORMAT of the result.
  *
+ * flags
+ *    Flags to control the behavior of the request.
+ *
  * xpath
  *    the xpath to get.
  *
@@ -389,7 +393,8 @@ extern int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
  */
 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, const char *xpath);
+                                    LYD_FORMAT result_type, uint8_t flags,
+                                    const char *xpath);
 
 /*
  * Destroy library and cleanup everything.
index 93ff6f012c92ba6e309d218edc05d60ad28efc56..88c1065fc84edf7577c9d8d95e37ae42d4b7883d 100644 (file)
@@ -233,16 +233,22 @@ _Static_assert(sizeof(struct mgmt_msg_tree_data) ==
                       offsetof(struct mgmt_msg_tree_data, result),
               "Size mismatch");
 
+/* Flags for get-data request */
+#define GET_DATA_FLAG_STATE    0x01    /* get only "config false" data */
+#define GET_DATA_FLAG_CONFIG   0x02    /* get only "config true" data */
+
 /**
  * struct mgmt_msg_get_data - frontend get-data request.
  *
  * @result_type: ``LYD_FORMAT`` for the returned result.
+ * @flags: combination of ``GET_DATA_FLAG_*`` flags.
  * @xpath: the query for the data to return.
  */
 struct mgmt_msg_get_data {
        struct mgmt_msg_header;
        uint8_t result_type;
-       uint8_t resv2[7];
+       uint8_t flags;
+       uint8_t resv2[6];
 
        alignas(8) char xpath[];
 };
index f1b7d621b7203c3032218ea6f96adce21a809603..3fc7c380830e73c32e9343300810480c12a4374e 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -4106,14 +4106,15 @@ 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,
-                              const char *xpath)
+                              uint8_t flags, const char *xpath)
 {
        LYD_FORMAT intern_format = result_type;
 
        vty->mgmt_req_id++;
 
        if (mgmt_fe_send_get_data_req(mgmt_fe_client, vty->mgmt_session_id,
-                                     vty->mgmt_req_id, intern_format, xpath)) {
+                                     vty->mgmt_req_id, intern_format, flags,
+                                     xpath)) {
                zlog_err("Failed to send GET-DATA to MGMTD session-id: %" PRIu64
                         " req-id %" PRIu64 ".",
                         vty->mgmt_session_id, vty->mgmt_req_id);
index 044e6433d17707dbc4e6700326e7ab43a9be90bc..73e0d238ad1d10a0e6e5b99995678b723e24e922 100644 (file)
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -421,7 +421,7 @@ extern int vty_mgmt_send_get_req(struct vty *vty, bool is_config,
                                 Mgmtd__DatastoreId datastore,
                                 const char **xpath_list, int num_req);
 extern int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type,
-                                     const char *xpath);
+                                     uint8_t flags, 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);
index 6527677d3185485b011bed93dc1cd03a73dfcf8b..d91987d8884f91d132c6e139c9d7b11dd9bc804e 100644 (file)
@@ -1181,7 +1181,7 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
        darr_free(snodes);
 
        clients = mgmt_be_interested_clients(msg->xpath, false);
-       if (!clients) {
+       if (!clients && !CHECK_FLAG(msg->flags, GET_DATA_FLAG_CONFIG)) {
                MGMTD_FE_ADAPTER_DBG("No backends provide xpath: %s for txn-id: %" PRIu64
                                     " session-id: %" PRIu64,
                                     msg->xpath, session->txn_id,
@@ -1207,8 +1207,8 @@ 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, simple_xpath,
-                                         msg->xpath);
+                                         msg->result_type, msg->flags,
+                                         simple_xpath, msg->xpath);
        if (ret) {
                /* destroy the just created txn */
                mgmt_destroy_txn(&session->txn_id);
index 679eaa7d7fd86d88d24fe6b0288e682e681c0549..3a2a23d9e9d849b05a6bc2c15c10040ab87b8e42 100644 (file)
@@ -2364,7 +2364,8 @@ 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,
-                               bool simple_xpath, const char *xpath)
+                               uint8_t flags, bool simple_xpath,
+                               const char *xpath)
 {
        struct mgmt_msg_get_tree *msg;
        struct mgmt_txn_ctx *txn;
@@ -2385,6 +2386,57 @@ int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id,
        get_tree->simple_xpath = simple_xpath;
        get_tree->xpath = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
 
+       if (CHECK_FLAG(flags, GET_DATA_FLAG_CONFIG)) {
+               struct mgmt_ds_ctx *ds =
+                       mgmt_ds_get_ctx_by_id(mm, MGMTD_DS_RUNNING);
+               struct nb_config *config = mgmt_ds_get_nb_config(ds);
+
+               if (config) {
+                       struct ly_set *set = NULL;
+                       LY_ERR err;
+
+                       err = lyd_find_xpath(config->dnode, xpath, &set);
+                       if (err) {
+                               get_tree->partial_error = err;
+                               goto state;
+                       }
+
+                       /*
+                        * If there's a single result, duplicate the returned
+                        * node. If there are multiple results, duplicate the
+                        * whole config and mark simple_xpath as false so the
+                        * result is trimmed later in txn_get_tree_data_done.
+                        */
+                       if (set->count == 1) {
+                               err = lyd_dup_single(set->dnodes[0], NULL,
+                                                    LYD_DUP_WITH_PARENTS |
+                                                            LYD_DUP_WITH_FLAGS |
+                                                            LYD_DUP_RECURSIVE,
+                                                    &get_tree->client_results);
+                               if (!err)
+                                       while (get_tree->client_results->parent)
+                                               get_tree->client_results = lyd_parent(
+                                                       get_tree->client_results);
+                       } else if (set->count > 1) {
+                               err = lyd_dup_siblings(config->dnode, NULL,
+                                                      LYD_DUP_RECURSIVE |
+                                                              LYD_DUP_WITH_FLAGS,
+                                                      &get_tree->client_results);
+                               if (!err)
+                                       get_tree->simple_xpath = false;
+                       }
+
+                       if (err)
+                               get_tree->partial_error = err;
+
+                       ly_set_free(set, NULL);
+               }
+       }
+state:
+       /* If we are only getting config, we are done */
+       if (!CHECK_FLAG(flags, GET_DATA_FLAG_STATE) || !clients)
+               return txn_get_tree_data_done(txn, txn_req);
+
        msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_get_tree, slen + 1,
                                        MTYPE_MSG_NATIVE_GET_TREE);
        msg->refer_id = txn_id;
index 39d8cde169534d424bf78528266449a925fce97f..3f27f2f07b78e59653f0d97a621028b71641b0f1 100644 (file)
@@ -203,6 +203,7 @@ extern int mgmt_txn_send_get_req(uint64_t txn_id, uint64_t req_id,
  *     req_id: FE client request identifier.
  *     clients: Bitmask of clients to send get-tree to.
  *     result_type: LYD_FORMAT result format.
+ *     flags: option flags for the request.
  *     simple_xpath: true if xpath is simple (only key predicates).
  *     xpath: The xpath to get the tree from.
  *
@@ -211,7 +212,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,
-                                      bool simple_xpath, const char *xpath);
+                                      uint8_t flags, bool simple_xpath,
+                                      const char *xpath);
 
 /*
  * Notifiy backend adapter on connection.
index 98e55788b4358795af52515cd3f9d5ebe05df7d9..e6f74c31290e920c365df9f8ec7a610edf95af92 100644 (file)
@@ -251,17 +251,23 @@ 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 [json|xml]$fmt",
+      "show mgmt get-data WORD$path [with-config|only-config]$content [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"
       "JSON output format\n"
       "XML output format\n")
 {
        LYD_FORMAT format = (fmt && fmt[0] == 'x') ? LYD_XML : LYD_JSON;
        int plen = strlen(path);
        char *xpath = NULL;
+       uint8_t flags = content ? GET_DATA_FLAG_CONFIG : GET_DATA_FLAG_STATE;
+
+       if (content && content[0] == 'w')
+               flags |= GET_DATA_FLAG_STATE;
 
        /* get rid of extraneous trailing slash-* or single '/' unless root */
        if (plen > 2 && ((path[plen - 2] == '/' && path[plen - 1] == '*') ||
@@ -272,7 +278,7 @@ DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
                path = xpath;
        }
 
-       vty_mgmt_send_get_data_req(vty, format, path);
+       vty_mgmt_send_get_data_req(vty, format, flags, path);
 
        if (xpath)
                XFREE(MTYPE_TMP, xpath);