mgmtd: add support for with-defaults parameter to get-data

Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
Igor Ryzhov 2024-01-29 22:50:26 +02:00
parent e2caf64ef7
commit 4317c8ffa6
12 changed files with 98 additions and 25 deletions

View File

@ -308,9 +308,10 @@ int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
/* /*
* Send get-data request. * Send get-data request.
*/ */
int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client, uint64_t session_id, int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
uint64_t req_id, LYD_FORMAT result_type, uint64_t session_id, uint64_t req_id,
uint8_t flags, const char *xpath) LYD_FORMAT result_type, uint8_t flags,
uint8_t defaults, const char *xpath)
{ {
struct mgmt_msg_get_data *msg; struct mgmt_msg_get_data *msg;
size_t xplen = strlen(xpath); size_t xplen = strlen(xpath);
@ -323,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->code = MGMT_MSG_CODE_GET_DATA;
msg->result_type = result_type; msg->result_type = result_type;
msg->flags = flags; msg->flags = flags;
msg->defaults = defaults;
strlcpy(msg->xpath, xpath, xplen + 1); strlcpy(msg->xpath, xpath, xplen + 1);
MGMTD_FE_CLIENT_DBG("Sending GET_DATA_REQ session-id %" PRIu64 MGMTD_FE_CLIENT_DBG("Sending GET_DATA_REQ session-id %" PRIu64

View File

@ -390,6 +390,9 @@ extern int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
* flags * flags
* Flags to control the behavior of the request. * Flags to control the behavior of the request.
* *
* defaults
* Options to control the reporting of default values.
*
* xpath * xpath
* the xpath to get. * the xpath to get.
* *
@ -399,7 +402,7 @@ 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, extern int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
uint64_t session_id, uint64_t req_id, uint64_t session_id, uint64_t req_id,
LYD_FORMAT result_type, uint8_t flags, LYD_FORMAT result_type, uint8_t flags,
const char *xpath); uint8_t defaults, const char *xpath);
/* /*
* Destroy library and cleanup everything. * Destroy library and cleanup everything.

View File

@ -240,17 +240,28 @@ _Static_assert(sizeof(struct mgmt_msg_tree_data) ==
#define GET_DATA_FLAG_CONFIG 0x02 /* get only "config true" data */ #define GET_DATA_FLAG_CONFIG 0x02 /* get only "config true" data */
#define GET_DATA_FLAG_EXACT 0x04 /* get exact data node instead of the full tree */ #define GET_DATA_FLAG_EXACT 0x04 /* get exact data node instead of the full tree */
/*
* Modes of reporting default values. Non-default values are always reported.
* These options reflect "with-defaults" modes as defined in RFC 6243.
*/
#define GET_DATA_DEFAULTS_EXPLICIT 0 /* "explicit" */
#define GET_DATA_DEFAULTS_TRIM 1 /* "trim" */
#define GET_DATA_DEFAULTS_ALL 2 /* "report-all" */
#define GET_DATA_DEFAULTS_ALL_ADD_TAG 3 /* "report-all-tagged" */
/** /**
* struct mgmt_msg_get_data - frontend get-data request. * struct mgmt_msg_get_data - frontend get-data request.
* *
* @result_type: ``LYD_FORMAT`` for the returned result. * @result_type: ``LYD_FORMAT`` for the returned result.
* @flags: combination of ``GET_DATA_FLAG_*`` flags. * @flags: combination of ``GET_DATA_FLAG_*`` flags.
* @defaults: one of ``GET_DATA_DEFAULTS_*`` values.
* @xpath: the query for the data to return. * @xpath: the query for the data to return.
*/ */
struct mgmt_msg_get_data { struct mgmt_msg_get_data {
struct mgmt_msg_header; struct mgmt_msg_header;
uint8_t result_type; uint8_t result_type;
uint8_t flags; uint8_t flags;
uint8_t defaults;
uint8_t resv2[6]; uint8_t resv2[6];
alignas(8) char xpath[]; alignas(8) char xpath[];

View File

@ -4102,7 +4102,8 @@ 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, int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type,
uint8_t flags, const char *xpath) uint8_t flags, uint8_t defaults,
const char *xpath)
{ {
LYD_FORMAT intern_format = result_type; LYD_FORMAT intern_format = result_type;
@ -4110,7 +4111,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, if (mgmt_fe_send_get_data_req(mgmt_fe_client, vty->mgmt_session_id,
vty->mgmt_req_id, intern_format, flags, vty->mgmt_req_id, intern_format, flags,
xpath)) { defaults, xpath)) {
zlog_err("Failed to send GET-DATA to MGMTD session-id: %" PRIu64 zlog_err("Failed to send GET-DATA to MGMTD session-id: %" PRIu64
" req-id %" PRIu64 ".", " req-id %" PRIu64 ".",
vty->mgmt_session_id, vty->mgmt_req_id); vty->mgmt_session_id, vty->mgmt_req_id);

View File

@ -421,7 +421,8 @@ extern int vty_mgmt_send_get_req(struct vty *vty, bool is_config,
Mgmtd__DatastoreId datastore, Mgmtd__DatastoreId datastore,
const char **xpath_list, int num_req); const char **xpath_list, int num_req);
extern int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type, extern int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type,
uint8_t flags, const char *xpath); uint8_t flags, uint8_t defaults,
const char *xpath);
extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id, extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id,
bool lock, bool scok); bool lock, bool scok);
extern void vty_mgmt_resume_response(struct vty *vty, int ret); extern void vty_mgmt_resume_response(struct vty *vty, int ret);

View File

@ -1080,7 +1080,7 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
*/ */
static int fe_adapter_send_tree_data(struct mgmt_fe_session_ctx *session, static int fe_adapter_send_tree_data(struct mgmt_fe_session_ctx *session,
uint64_t req_id, bool short_circuit_ok, uint64_t req_id, bool short_circuit_ok,
uint8_t result_type, uint8_t result_type, uint32_t wd_options,
const struct lyd_node *tree, const struct lyd_node *tree,
int partial_error) int partial_error)
@ -1105,8 +1105,7 @@ static int fe_adapter_send_tree_data(struct mgmt_fe_session_ctx *session,
darrp = mgmt_msg_native_get_darrp(msg); darrp = mgmt_msg_native_get_darrp(msg);
ret = yang_print_tree_append(darrp, tree, result_type, ret = yang_print_tree_append(darrp, tree, result_type,
(LYD_PRINT_WD_EXPLICIT | (wd_options | LYD_PRINT_WITHSIBLINGS));
LYD_PRINT_WITHSIBLINGS));
if (ret != LY_SUCCESS) { if (ret != LY_SUCCESS) {
MGMTD_FE_ADAPTER_ERR("Error building get-tree result for client %s session-id %" PRIu64 MGMTD_FE_ADAPTER_ERR("Error building get-tree result for client %s session-id %" PRIu64
" req-id %" PRIu64 " req-id %" PRIu64
@ -1147,6 +1146,7 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
char *xpath_resolved = NULL; char *xpath_resolved = NULL;
uint64_t req_id = msg->req_id; uint64_t req_id = msg->req_id;
uint64_t clients; uint64_t clients;
uint32_t wd_options;
bool simple_xpath; bool simple_xpath;
LY_ERR err; LY_ERR err;
int ret; int ret;
@ -1171,6 +1171,25 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
goto done; goto done;
} }
switch (msg->defaults) {
case GET_DATA_DEFAULTS_EXPLICIT:
wd_options = LYD_PRINT_WD_EXPLICIT;
break;
case GET_DATA_DEFAULTS_TRIM:
wd_options = LYD_PRINT_WD_TRIM;
break;
case GET_DATA_DEFAULTS_ALL:
wd_options = LYD_PRINT_WD_ALL;
break;
case GET_DATA_DEFAULTS_ALL_ADD_TAG:
wd_options = LYD_PRINT_WD_IMPL_TAG;
break;
default:
fe_adapter_send_error(session, req_id, false, -EINVAL,
"Invalid defaults value %u for session-id: %" PRIu64,
msg->defaults, session->session_id);
goto done;
}
err = yang_resolve_snode_xpath(ly_native_ctx, msg->xpath, &snodes, err = yang_resolve_snode_xpath(ly_native_ctx, msg->xpath, &snodes,
&simple_xpath); &simple_xpath);
@ -1190,7 +1209,7 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
session->session_id); session->session_id);
fe_adapter_send_tree_data(session, req_id, false, fe_adapter_send_tree_data(session, req_id, false,
msg->result_type, NULL, 0); msg->result_type, wd_options, NULL, 0);
goto done; goto done;
} }
@ -1210,7 +1229,7 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
/* Create a GET-TREE request under the transaction */ /* Create a GET-TREE request under the transaction */
ret = mgmt_txn_send_get_tree_oper(session->txn_id, req_id, clients, ret = mgmt_txn_send_get_tree_oper(session->txn_id, req_id, clients,
msg->result_type, msg->flags, msg->result_type, msg->flags,
simple_xpath, msg->xpath); wd_options, simple_xpath, msg->xpath);
if (ret) { if (ret) {
/* destroy the just created txn */ /* destroy the just created txn */
mgmt_destroy_txn(&session->txn_id); mgmt_destroy_txn(&session->txn_id);
@ -1469,6 +1488,7 @@ int mgmt_fe_send_get_reply(uint64_t session_id, uint64_t txn_id,
int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id, int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
uint64_t req_id, LYD_FORMAT result_type, uint64_t req_id, LYD_FORMAT result_type,
uint32_t wd_options,
const struct lyd_node *tree, const struct lyd_node *tree,
int partial_error, bool short_circuit_ok) int partial_error, bool short_circuit_ok)
{ {
@ -1480,7 +1500,8 @@ int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
return -1; return -1;
ret = fe_adapter_send_tree_data(session, req_id, short_circuit_ok, ret = fe_adapter_send_tree_data(session, req_id, short_circuit_ok,
result_type, tree, partial_error); result_type, wd_options, tree,
partial_error);
mgmt_destroy_txn(&session->txn_id); mgmt_destroy_txn(&session->txn_id);

View File

@ -148,6 +148,7 @@ extern int mgmt_fe_send_get_reply(uint64_t session_id, uint64_t txn_id,
* txn_id: the txn_id this data pertains to * txn_id: the txn_id this data pertains to
* req_id: the req id for the get_tree message * req_id: the req id for the get_tree message
* result_type: the format of the result data. * result_type: the format of the result data.
* wd_options: with-defaults options.
* tree: the results. * tree: the results.
* partial_error: if there were errors while gather results. * partial_error: if there were errors while gather results.
* short_circuit_ok: True if OK to short-circuit the call. * short_circuit_ok: True if OK to short-circuit the call.
@ -156,12 +157,11 @@ extern int mgmt_fe_send_get_reply(uint64_t session_id, uint64_t txn_id,
* the return value from the underlying send function. * the return value from the underlying send function.
* *
*/ */
extern int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id, extern int
uint64_t req_id, mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
LYD_FORMAT result_type, uint64_t req_id, LYD_FORMAT result_type,
const struct lyd_node *tree, uint32_t wd_options, const struct lyd_node *tree,
int partial_error, int partial_error, bool short_circuit_ok);
bool short_circuit_ok);
/** /**
* Send an error back to the FE client using native messaging. * Send an error back to the FE client using native messaging.

View File

@ -144,6 +144,16 @@ static struct frr_signal_t mgmt_signals[] = {
extern const struct frr_yang_module_info frr_staticd_cli_info; extern const struct frr_yang_module_info frr_staticd_cli_info;
#endif #endif
/*
* These are modules that are only needed by mgmtd and hence not included into
* the lib and backend daemons.
*/
const struct frr_yang_module_info ietf_netconf_with_defaults_info = {
.name = "ietf-netconf-with-defaults",
.ignore_cfg_cbs = true,
.nodes = { { .xpath = NULL } },
};
/* /*
* These are stub info structs that are used to load the modules used by backend * These are stub info structs that are used to load the modules used by backend
* clients into mgmtd. The modules are used by libyang in order to support * clients into mgmtd. The modules are used by libyang in order to support
@ -167,6 +177,9 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
&frr_vrf_info, &frr_vrf_info,
&frr_affinity_map_cli_info, &frr_affinity_map_cli_info,
/* mgmtd-only modules */
&ietf_netconf_with_defaults_info,
/* /*
* YANG module info used by backend clients get added here. * YANG module info used by backend clients get added here.
*/ */

View File

@ -175,6 +175,7 @@ struct txn_req_get_tree {
uint64_t recv_clients; /* Bitmask of clients recv reply from */ uint64_t recv_clients; /* Bitmask of clients recv reply from */
int32_t partial_error; /* an error while gather results */ int32_t partial_error; /* an error while gather results */
uint8_t result_type; /* LYD_FORMAT for results */ uint8_t result_type; /* LYD_FORMAT for results */
uint8_t wd_options; /* LYD_PRINT_WD_* flags for results */
uint8_t exact; /* if exact node is requested */ uint8_t exact; /* if exact node is requested */
uint8_t simple_xpath; /* if xpath is simple */ uint8_t simple_xpath; /* if xpath is simple */
struct lyd_node *client_results; /* result tree from clients */ struct lyd_node *client_results; /* result tree from clients */
@ -1282,6 +1283,7 @@ static int txn_get_tree_data_done(struct mgmt_txn_ctx *txn,
txn->txn_id, txn->txn_id,
txn_req->req_id, txn_req->req_id,
get_tree->result_type, get_tree->result_type,
get_tree->wd_options,
result, result,
get_tree->partial_error, get_tree->partial_error,
false); false);
@ -2340,8 +2342,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, int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id,
uint64_t clients, LYD_FORMAT result_type, uint64_t clients, LYD_FORMAT result_type,
uint8_t flags, bool simple_xpath, uint8_t flags, uint32_t wd_options,
const char *xpath) bool simple_xpath, const char *xpath)
{ {
struct mgmt_msg_get_tree *msg; struct mgmt_msg_get_tree *msg;
struct mgmt_txn_ctx *txn; struct mgmt_txn_ctx *txn;
@ -2359,6 +2361,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); txn_req = mgmt_txn_req_alloc(txn, req_id, MGMTD_TXN_PROC_GETTREE);
get_tree = txn_req->req.get_tree; get_tree = txn_req->req.get_tree;
get_tree->result_type = result_type; get_tree->result_type = result_type;
get_tree->wd_options = wd_options;
get_tree->exact = CHECK_FLAG(flags, GET_DATA_FLAG_EXACT); get_tree->exact = CHECK_FLAG(flags, GET_DATA_FLAG_EXACT);
get_tree->simple_xpath = simple_xpath; get_tree->simple_xpath = simple_xpath;
get_tree->xpath = XSTRDUP(MTYPE_MGMTD_XPATH, xpath); get_tree->xpath = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);

View File

@ -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. * clients: Bitmask of clients to send get-tree to.
* result_type: LYD_FORMAT result format. * result_type: LYD_FORMAT result format.
* flags: option flags for the request. * flags: option flags for the request.
* wd_options: LYD_PRINT_WD_* flags for the result.
* simple_xpath: true if xpath is simple (only key predicates). * simple_xpath: true if xpath is simple (only key predicates).
* xpath: The xpath to get the tree from. * xpath: The xpath to get the tree from.
* *
@ -212,8 +213,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, extern int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id,
uint64_t clients, LYD_FORMAT result_type, uint64_t clients, LYD_FORMAT result_type,
uint8_t flags, bool simple_xpath, uint8_t flags, uint32_t wd_options,
const char *xpath); bool simple_xpath, const char *xpath);
/* /*
* Notifiy backend adapter on connection. * Notifiy backend adapter on connection.

View File

@ -258,7 +258,7 @@ DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd,
} }
DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd, DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
"show mgmt get-data WORD$path [with-config|only-config]$content [exact]$exact [json|xml]$fmt", "show mgmt get-data WORD$path [with-config|only-config]$content [exact]$exact [with-defaults <trim|all-tag|all>$wd] [json|xml]$fmt",
SHOW_STR SHOW_STR
MGMTD_STR MGMTD_STR
"Get a data from the operational datastore\n" "Get a data from the operational datastore\n"
@ -266,6 +266,10 @@ DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
"Include \"config true\" data\n" "Include \"config true\" data\n"
"Get only \"config true\" data\n" "Get only \"config true\" data\n"
"Get exact node instead of the whole data tree\n" "Get exact node instead of the whole data tree\n"
"Configure 'with-defaults' mode per RFC 6243 (\"explicit\" mode by default)\n"
"Use \"trim\" mode\n"
"Use \"report-all-tagged\" mode\n"
"Use \"report-all\" mode\n"
"JSON output format\n" "JSON output format\n"
"XML output format\n") "XML output format\n")
{ {
@ -273,6 +277,7 @@ DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
int plen = strlen(path); int plen = strlen(path);
char *xpath = NULL; char *xpath = NULL;
uint8_t flags = content ? GET_DATA_FLAG_CONFIG : GET_DATA_FLAG_STATE; uint8_t flags = content ? GET_DATA_FLAG_CONFIG : GET_DATA_FLAG_STATE;
uint8_t defaults = GET_DATA_DEFAULTS_EXPLICIT;
if (content && content[0] == 'w') if (content && content[0] == 'w')
flags |= GET_DATA_FLAG_STATE; flags |= GET_DATA_FLAG_STATE;
@ -280,6 +285,15 @@ DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
if (exact) if (exact)
flags |= GET_DATA_FLAG_EXACT; flags |= GET_DATA_FLAG_EXACT;
if (wd) {
if (wd[0] == 't')
defaults = GET_DATA_DEFAULTS_TRIM;
else if (wd[3] == '-')
defaults = GET_DATA_DEFAULTS_ALL_ADD_TAG;
else
defaults = GET_DATA_DEFAULTS_ALL;
}
/* get rid of extraneous trailing slash-* or single '/' unless root */ /* get rid of extraneous trailing slash-* or single '/' unless root */
if (plen > 2 && ((path[plen - 2] == '/' && path[plen - 1] == '*') || if (plen > 2 && ((path[plen - 2] == '/' && path[plen - 1] == '*') ||
(path[plen - 2] != '/' && path[plen - 1] == '/'))) { (path[plen - 2] != '/' && path[plen - 1] == '/'))) {
@ -289,7 +303,7 @@ DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
path = xpath; path = xpath;
} }
vty_mgmt_send_get_data_req(vty, format, flags, path); vty_mgmt_send_get_data_req(vty, format, flags, defaults, path);
if (xpath) if (xpath)
XFREE(MTYPE_TMP, xpath); XFREE(MTYPE_TMP, xpath);

View File

@ -61,6 +61,9 @@ mgmtd_mgmtd_SOURCES = \
# end # end
nodist_mgmtd_mgmtd_SOURCES = \ nodist_mgmtd_mgmtd_SOURCES = \
yang/frr-zebra.yang.c \ yang/frr-zebra.yang.c \
yang/ietf/ietf-netconf-acm.yang.c \
yang/ietf/ietf-netconf.yang.c \
yang/ietf/ietf-netconf-with-defaults.yang.c \
# nothing # nothing
mgmtd_mgmtd_CFLAGS = $(AM_CFLAGS) -I ./ mgmtd_mgmtd_CFLAGS = $(AM_CFLAGS) -I ./
mgmtd_mgmtd_LDADD = mgmtd/libmgmtd.a lib/libfrr.la $(LIBCAP) $(LIBM) $(LIBYANG_LIBS) $(UST_LIBS) mgmtd_mgmtd_LDADD = mgmtd/libmgmtd.a lib/libfrr.la $(LIBCAP) $(LIBM) $(LIBYANG_LIBS) $(UST_LIBS)