Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mgmt get-data improvements #15246

Merged
merged 6 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions lib/mgmt_fe_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,10 @@ 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,
uint8_t flags, const char *xpath)
int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
uint64_t session_id, uint64_t req_id,
uint8_t datastore, LYD_FORMAT result_type,
uint8_t flags, uint8_t defaults, const char *xpath)
{
struct mgmt_msg_get_data *msg;
size_t xplen = strlen(xpath);
Expand All @@ -323,6 +324,8 @@ 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->flags = flags;
msg->defaults = defaults;
msg->datastore = datastore;
strlcpy(msg->xpath, xpath, xplen + 1);

MGMTD_FE_CLIENT_DBG("Sending GET_DATA_REQ session-id %" PRIu64
Expand Down
9 changes: 8 additions & 1 deletion lib/mgmt_fe_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,18 @@ extern int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
* req_id
* Client request ID.
*
* datastore
* Datastore for getting data.
*
* result_type
* The LYD_FORMAT of the result.
*
* flags
* Flags to control the behavior of the request.
*
* defaults
* Options to control the reporting of default values.
*
* xpath
* the xpath to get.
*
Expand All @@ -398,7 +404,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, uint8_t flags,
uint8_t datastore, LYD_FORMAT result_type,
uint8_t flags, uint8_t defaults,
const char *xpath);

/*
Expand Down
42 changes: 39 additions & 3 deletions lib/mgmt_msg_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,30 @@ DECLARE_MTYPE(MSG_NATIVE_NOTIFY);
#define MGMT_MSG_CODE_GET_DATA 3
#define MGMT_MSG_CODE_NOTIFY 4

/*
* Datastores
*/
#define MGMT_MSG_DATASTORE_STARTUP 0
#define MGMT_MSG_DATASTORE_CANDIDATE 1
#define MGMT_MSG_DATASTORE_RUNNING 2
#define MGMT_MSG_DATASTORE_OPERATIONAL 3

/*
* Formats
*/
#define MGMT_MSG_FORMAT_XML 1
#define MGMT_MSG_FORMAT_JSON 2
#define MGMT_MSG_FORMAT_BINARY 3 /* non-standard libyang internal format */

/*
* Now we're using LYD_FORMAT directly to avoid mapping code, but having our
* own definitions allows us to create such a mapping in the future if libyang
* makes a backwards incompatible change.
*/
_Static_assert(MGMT_MSG_FORMAT_XML == LYD_XML, "Format mismatch");
_Static_assert(MGMT_MSG_FORMAT_JSON == LYD_JSON, "Format mismatch");
_Static_assert(MGMT_MSG_FORMAT_BINARY == LYD_LYB, "Format mismatch");

/**
* struct mgmt_msg_header - Header common to all native messages.
*
Expand Down Expand Up @@ -236,22 +260,34 @@ _Static_assert(sizeof(struct mgmt_msg_tree_data) ==
"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 */
#define GET_DATA_FLAG_STATE 0x01 /* include "config false" data */
#define GET_DATA_FLAG_CONFIG 0x02 /* include "config true" data */
#define GET_DATA_FLAG_EXACT 0x04 /* get exact data node instead of the full tree */

/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also while in here, let's remove only from the comments above since that's not what is actually happening. These are flags and you can have both set in which case both "config" and "data" are returned not "only data" and "only config" :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* 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.
*
* @result_type: ``LYD_FORMAT`` for the returned result.
* @flags: combination of ``GET_DATA_FLAG_*`` flags.
* @defaults: one of ``GET_DATA_DEFAULTS_*`` values.
* @xpath: the query for the data to return.
*/
struct mgmt_msg_get_data {
struct mgmt_msg_header;
uint8_t result_type;
uint8_t flags;
uint8_t resv2[6];
uint8_t defaults;
uint8_t datastore;
uint8_t resv2[4];

alignas(8) char xpath[];
};
Expand Down
9 changes: 5 additions & 4 deletions lib/vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -4101,16 +4101,17 @@ int vty_mgmt_send_get_req(struct vty *vty, bool is_config,
return 0;
}

int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type,
uint8_t flags, const char *xpath)
int vty_mgmt_send_get_data_req(struct vty *vty, uint8_t datastore,
LYD_FORMAT result_type, uint8_t flags,
uint8_t defaults, 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, flags,
xpath)) {
vty->mgmt_req_id, datastore,
intern_format, flags, defaults, xpath)) {
zlog_err("Failed to send GET-DATA to MGMTD session-id: %" PRIu64
" req-id %" PRIu64 ".",
vty->mgmt_session_id, vty->mgmt_req_id);
Expand Down
5 changes: 3 additions & 2 deletions lib/vty.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,9 @@ extern int vty_mgmt_send_commit_config(struct vty *vty, bool validate_only,
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,
uint8_t flags, const char *xpath);
extern int vty_mgmt_send_get_data_req(struct vty *vty, uint8_t datastore,
LYD_FORMAT result_type, uint8_t flags,
uint8_t defaults, 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);
Expand Down
62 changes: 47 additions & 15 deletions mgmtd/mgmt_fe_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1080,13 +1080,12 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
*/
static int fe_adapter_send_tree_data(struct mgmt_fe_session_ctx *session,
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,
int partial_error)

{
struct mgmt_msg_tree_data *msg;
struct lyd_node *empty = NULL;
uint8_t **darrp = NULL;
int ret = 0;

Expand All @@ -1098,15 +1097,9 @@ static int fe_adapter_send_tree_data(struct mgmt_fe_session_ctx *session,
msg->partial_error = partial_error;
msg->result_type = result_type;

if (!tree) {
empty = yang_dnode_new(ly_native_ctx, false);
tree = empty;
}

darrp = mgmt_msg_native_get_darrp(msg);
ret = yang_print_tree_append(darrp, tree, result_type,
(LYD_PRINT_WD_EXPLICIT |
LYD_PRINT_WITHSIBLINGS));
(wd_options | LYD_PRINT_WITHSIBLINGS));
if (ret != LY_SUCCESS) {
MGMTD_FE_ADAPTER_ERR("Error building get-tree result for client %s session-id %" PRIu64
" req-id %" PRIu64
Expand All @@ -1126,8 +1119,6 @@ static int fe_adapter_send_tree_data(struct mgmt_fe_session_ctx *session,
mgmt_msg_native_get_msg_len(msg),
short_circuit_ok);
done:
if (empty)
yang_dnode_free(empty);
mgmt_msg_native_free_msg(msg);

return ret;
Expand All @@ -1146,7 +1137,9 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
struct lysc_node **snodes = NULL;
char *xpath_resolved = NULL;
uint64_t req_id = msg->req_id;
Mgmtd__DatastoreId ds_id;
uint64_t clients;
uint32_t wd_options;
bool simple_xpath;
LY_ERR err;
int ret;
Expand All @@ -1171,6 +1164,43 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
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;
}

switch (msg->datastore) {
case MGMT_MSG_DATASTORE_CANDIDATE:
ds_id = MGMTD_DS_CANDIDATE;
break;
case MGMT_MSG_DATASTORE_RUNNING:
ds_id = MGMTD_DS_RUNNING;
break;
case MGMT_MSG_DATASTORE_OPERATIONAL:
ds_id = MGMTD_DS_OPERATIONAL;
break;
default:
fe_adapter_send_error(session, req_id, false, -EINVAL,
"Unsupported datastore %" PRIu8
" requested from session-id: %" PRIu64,
msg->datastore, session->session_id);
goto done;
}

err = yang_resolve_snode_xpath(ly_native_ctx, msg->xpath, &snodes,
&simple_xpath);
Expand All @@ -1190,7 +1220,7 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
session->session_id);

fe_adapter_send_tree_data(session, req_id, false,
msg->result_type, NULL, 0);
msg->result_type, wd_options, NULL, 0);
goto done;
}

Expand All @@ -1209,8 +1239,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, msg->flags,
simple_xpath, msg->xpath);
ds_id, msg->result_type, msg->flags,
wd_options, simple_xpath, msg->xpath);
if (ret) {
/* destroy the just created txn */
mgmt_destroy_txn(&session->txn_id);
Expand Down Expand Up @@ -1469,6 +1499,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,
uint64_t req_id, LYD_FORMAT result_type,
uint32_t wd_options,
const struct lyd_node *tree,
int partial_error, bool short_circuit_ok)
{
Expand All @@ -1480,7 +1511,8 @@ int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
return -1;

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);

Expand Down
12 changes: 6 additions & 6 deletions mgmtd/mgmt_fe_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
* req_id: the req id for the get_tree message
* result_type: the format of the result data.
* wd_options: with-defaults options.
* tree: the results.
* partial_error: if there were errors while gather results.
* short_circuit_ok: True if OK to short-circuit the call.
Expand All @@ -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.
*
*/
extern int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
uint64_t req_id,
LYD_FORMAT result_type,
const struct lyd_node *tree,
int partial_error,
bool short_circuit_ok);
extern int
mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
uint64_t req_id, LYD_FORMAT result_type,
uint32_t wd_options, const struct lyd_node *tree,
int partial_error, bool short_circuit_ok);

/**
* Send an error back to the FE client using native messaging.
Expand Down
13 changes: 13 additions & 0 deletions mgmtd/mgmt_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ static struct frr_signal_t mgmt_signals[] = {
extern const struct frr_yang_module_info frr_staticd_cli_info;
#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
* clients into mgmtd. The modules are used by libyang in order to support
Expand All @@ -167,6 +177,9 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
&frr_vrf_info,
&frr_affinity_map_cli_info,

/* mgmtd-only modules */
&ietf_netconf_with_defaults_info,

/*
* YANG module info used by backend clients get added here.
*/
Expand Down
Loading
Loading