diff options
Diffstat (limited to 'mgmtd')
-rw-r--r-- | mgmtd/mgmt_fe_adapter.c | 18 | ||||
-rw-r--r-- | mgmtd/mgmt_main.c | 7 | ||||
-rw-r--r-- | mgmtd/mgmt_txn.c | 64 | ||||
-rw-r--r-- | mgmtd/mgmt_txn.h | 4 | ||||
-rw-r--r-- | mgmtd/mgmt_vty.c | 14 |
5 files changed, 93 insertions, 14 deletions
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c index a69d27fc5..d91987d88 100644 --- a/mgmtd/mgmt_fe_adapter.c +++ b/mgmtd/mgmt_fe_adapter.c @@ -1132,15 +1132,15 @@ done: } /** - * fe_adapter_handle_get_tree() - Handle a get-tree message from a FE client. + * fe_adapter_handle_get_data() - Handle a get-tree message from a FE client. * @session: the client session. * @msg_raw: the message data. * @msg_len: the length of the message data. */ -static void fe_adapter_handle_get_tree(struct mgmt_fe_session_ctx *session, +static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session, void *__msg, size_t msg_len) { - struct mgmt_msg_get_tree *msg = __msg; + struct mgmt_msg_get_data *msg = __msg; struct lysc_node **snodes = NULL; char *xpath_resolved = NULL; uint64_t req_id = msg->req_id; @@ -1149,7 +1149,7 @@ static void fe_adapter_handle_get_tree(struct mgmt_fe_session_ctx *session, LY_ERR err; int ret; - MGMTD_FE_ADAPTER_DBG("Received get-tree request from client %s for session-id %" PRIu64 + MGMTD_FE_ADAPTER_DBG("Received get-data request from client %s for session-id %" PRIu64 " req-id %" PRIu64, session->adapter->name, session->session_id, msg->req_id); @@ -1181,7 +1181,7 @@ static void fe_adapter_handle_get_tree(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_tree(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); @@ -1238,8 +1238,8 @@ static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter, assert(session->adapter == adapter); switch (msg->code) { - case MGMT_MSG_CODE_GET_TREE: - fe_adapter_handle_get_tree(session, msg, msg_len); + case MGMT_MSG_CODE_GET_DATA: + fe_adapter_handle_get_data(session, msg, msg_len); break; default: MGMTD_FE_ADAPTER_ERR("unknown native message session-id %" PRIu64 diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c index 72bb353b2..743091e5c 100644 --- a/mgmtd/mgmt_main.c +++ b/mgmtd/mgmt_main.c @@ -22,6 +22,7 @@ static const struct option longopts[] = { {"skip_runas", no_argument, NULL, 'S'}, {"no_zebra", no_argument, NULL, 'Z'}, {"socket_size", required_argument, NULL, 's'}, + {"vrfwnetns", no_argument, NULL, 'n'}, {0}}; static void mgmt_exit(int); @@ -237,6 +238,9 @@ int main(int argc, char **argv) case 's': buffer_size = atoi(optarg); break; + case 'n': + vrf_configure_backend(VRF_BACKEND_NETNS); + break; default: frr_help_exit(1); break; @@ -249,6 +253,9 @@ int main(int argc, char **argv) /* VRF commands initialization. */ vrf_cmd_init(NULL); + /* Interface commands initialization. */ + if_cmd_init(NULL); + /* MGMTD related initialization. */ mgmt_init(); diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c index 679eaa7d7..842e13cf1 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); @@ -2364,7 +2371,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; @@ -2382,9 +2390,61 @@ 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 = CHECK_FLAG(flags, GET_DATA_FLAG_EXACT); 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; diff --git a/mgmtd/mgmt_txn.h b/mgmtd/mgmt_txn.h index 39d8cde16..3f27f2f07 100644 --- a/mgmtd/mgmt_txn.h +++ b/mgmtd/mgmt_txn.h @@ -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. diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index 2591930e4..f4b24acf3 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -251,17 +251,27 @@ 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 [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") { 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; + + if (exact) + flags |= GET_DATA_FLAG_EXACT; /* get rid of extraneous trailing slash-* or single '/' unless root */ if (plen > 2 && ((path[plen - 2] == '/' && path[plen - 1] == '*') || @@ -272,7 +282,7 @@ DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd, path = xpath; } - vty_mgmt_send_get_tree_req(vty, format, path); + vty_mgmt_send_get_data_req(vty, format, flags, path); if (xpath) XFREE(MTYPE_TMP, xpath); |