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

mgmtd get-data request expansion #15154

Merged
merged 9 commits into from
Jan 15, 2024
3 changes: 2 additions & 1 deletion doc/user/zebra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
When *Zebra* starts with this option, the VRF backend is based on Linux
network namespaces. That implies that all network namespaces discovered by
ZEBRA will create an associated VRF. The other daemons will operate on the VRF
VRF defined by *Zebra*, as usual.
VRF defined by *Zebra*, as usual. If this option is specified when running
*Zebra*, one must also specify the same option for *mgmtd*.

.. seealso:: :ref:`zebra-vrf`

Expand Down
19 changes: 10 additions & 9 deletions lib/mgmt_fe_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,25 +306,26 @@ int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
}

/*
* Send get-tree request.
* Send get-data request.
*/
int mgmt_fe_send_get_tree_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_tree *msg;
struct mgmt_msg_get_data *msg;
size_t xplen = strlen(xpath);
int ret;

msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_get_tree, xplen + 1,
MTYPE_MSG_NATIVE_GET_TREE);
msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_get_data, xplen + 1,
MTYPE_MSG_NATIVE_GET_DATA);
msg->refer_id = session_id;
msg->req_id = req_id;
msg->code = MGMT_MSG_CODE_GET_TREE;
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_TREE_REQ session-id %" PRIu64
MGMTD_FE_CLIENT_DBG("Sending GET_DATA_REQ session-id %" PRIu64
" req-id %" PRIu64 " xpath: %s",
session_id, req_id, xpath);

Expand Down
11 changes: 8 additions & 3 deletions lib/mgmt_fe_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ extern "C" {
#include "mgmt_pb.h"
#include "frrevent.h"
#include "mgmt_defines.h"
#include "mgmt_msg_native.h"

/***************************************************************
* Macros
Expand Down Expand Up @@ -367,7 +368,7 @@ extern int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
int num_reqs);

/*
* Send GET-TREE to MGMTD daemon.
* Send GET-DATA to MGMTD daemon.
*
* client
* Client object.
Expand All @@ -381,15 +382,19 @@ 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.
*
* Returns:
* 0 on success, otherwise msg_conn_send_msg() return values.
*/
extern int mgmt_fe_send_get_tree_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.
Expand Down
1 change: 1 addition & 0 deletions lib/mgmt_msg_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_MSG, "native mgmt msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_ERROR, "native error msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_GET_TREE, "native get tree msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_TREE_DATA, "native tree data msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_GET_DATA, "native get data msg");

int vmgmt_msg_native_send_error(struct msg_conn *conn, uint64_t sess_or_txn_id,
uint64_t req_id, bool short_circuit_ok,
Expand Down
28 changes: 27 additions & 1 deletion lib/mgmt_msg_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,15 @@ DECLARE_MTYPE(MSG_NATIVE_MSG);
DECLARE_MTYPE(MSG_NATIVE_ERROR);
DECLARE_MTYPE(MSG_NATIVE_GET_TREE);
DECLARE_MTYPE(MSG_NATIVE_TREE_DATA);
DECLARE_MTYPE(MSG_NATIVE_GET_DATA);

/*
* Native message codes
*/
#define MGMT_MSG_CODE_ERROR 0
#define MGMT_MSG_CODE_GET_TREE 1
#define MGMT_MSG_CODE_TREE_DATA 2
#define MGMT_MSG_CODE_GET_DATA 3

/**
* struct mgmt_msg_header - Header common to all native messages.
Expand Down Expand Up @@ -193,7 +195,7 @@ _Static_assert(sizeof(struct mgmt_msg_error) ==
"Size mismatch");

/**
* struct mgmt_msg_get_tree - Message carrying xpath query request.
* struct mgmt_msg_get_tree - backend oper data request.
*
* @result_type: ``LYD_FORMAT`` for the returned result.
* @xpath: the query for the data to return.
Expand Down Expand Up @@ -231,6 +233,30 @@ _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 */
#define GET_DATA_FLAG_EXACT 0x04 /* get exact data node instead of the full tree */

/**
* 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 flags;
uint8_t resv2[6];

alignas(8) char xpath[];
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just replace mgmt_msg_get_tree with this? Even with the expanded functionality coming in later commits? I don't see any point in having a specialized get-tree message that can be exactly replaced by this one with a couple extra params.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the code is more clear if we have separate messages for the frontend and for the backend. There are new fields in the frontend message and there will be more later (like datastore, with-defaults, etc., to cover the whole NETCONF/RESTCONF functionality). And all these new fields don't make sense on the backend.

_Static_assert(sizeof(struct mgmt_msg_get_data) ==
offsetof(struct mgmt_msg_get_data, xpath),
"Size mismatch");

#define MGMT_MSG_VALIDATE_NUL_TERM(msgp, len) \
((len) >= sizeof(*msg) + 1 && ((char *)msgp)[(len)-1] == 0)

Expand Down
12 changes: 11 additions & 1 deletion lib/northbound_oper.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,18 @@ static enum nb_error nb_op_ys_init_node_infos(struct nb_op_yield_state *ys)

/* Move up to the container if on a leaf currently. */
if (node &&
!CHECK_FLAG(node->schema->nodetype, LYS_CONTAINER | LYS_LIST))
!CHECK_FLAG(node->schema->nodetype, LYS_CONTAINER | LYS_LIST)) {
struct lyd_node *leaf = node;

node = &node->parent->node;

/*
* If the leaf is not a key, delete it, because it has a wrong
* empty value.
*/
if (!lysc_is_key(leaf->schema))
lyd_free_tree(leaf);
}
assert(!node ||
CHECK_FLAG(node->schema->nodetype, LYS_CONTAINER | LYS_LIST));
if (!node)
Expand Down
15 changes: 8 additions & 7 deletions lib/vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -4105,23 +4105,24 @@ int vty_mgmt_send_get_req(struct vty *vty, bool is_config,
return 0;
}

int vty_mgmt_send_get_tree_req(struct vty *vty, LYD_FORMAT result_type,
const char *xpath)
int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type,
uint8_t flags, const char *xpath)
{
LYD_FORMAT intern_format = result_type;

vty->mgmt_req_id++;

if (mgmt_fe_send_get_tree_req(mgmt_fe_client, vty->mgmt_session_id,
vty->mgmt_req_id, intern_format, xpath)) {
zlog_err("Failed to send GET-TREE to MGMTD session-id: %" PRIu64
if (mgmt_fe_send_get_data_req(mgmt_fe_client, vty->mgmt_session_id,
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);
vty_out(vty, "Failed to send GET-TREE to MGMTD!\n");
vty_out(vty, "Failed to send GET-DATA to MGMTD!\n");
return -1;
}

vty->mgmt_req_pending_cmd = "MESSAGE_GET_TREE_REQ";
vty->mgmt_req_pending_cmd = "MESSAGE_GET_DATA_REQ";
vty->mgmt_req_pending_data = result_type;

return 0;
Expand Down
4 changes: 2 additions & 2 deletions lib/vty.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,8 @@ 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_tree_req(struct vty *vty, LYD_FORMAT result_type,
const char *xpath);
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_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
27 changes: 15 additions & 12 deletions lib/yang.c
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath)
}
return LY_SUCCESS;
#else
struct lyd_node *node;
struct lyd_node *node, *sib;
struct lyd_node **remove = NULL;
struct ly_set *set = NULL;
uint32_t i;
Expand Down Expand Up @@ -1123,18 +1123,21 @@ LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath)
}

darr_ensure_cap(remove, 128);
LYD_TREE_DFS_BEGIN (*root, node) {
/*
* If this is a direct matching node then include it's subtree
* which won't be marked and would otherwise be removed.
*/
if (node->priv == (void *)2)
LYD_TREE_DFS_continue = 1;
else if (!node->priv) {
*darr_append(remove) = node;
LYD_TREE_DFS_continue = 1;
LY_LIST_FOR(*root, sib) {
LYD_TREE_DFS_BEGIN (sib, node) {
/*
* If this is a direct matching node then include its
* subtree which won't be marked and would otherwise
* be removed.
*/
if (node->priv == (void *)2)
LYD_TREE_DFS_continue = 1;
else if (!node->priv) {
*darr_append(remove) = node;
LYD_TREE_DFS_continue = 1;
}
LYD_TREE_DFS_END(sib, node);
}
LYD_TREE_DFS_END(*root, node);
}
darr_foreach_i (remove, i) {
if (remove[i] == *root)
Expand Down
18 changes: 9 additions & 9 deletions mgmtd/mgmt_fe_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1132,15 +1132,15 @@ static int fe_adapter_send_tree_data(struct mgmt_fe_session_ctx *session,
}

/**
* 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;
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions mgmtd/mgmt_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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();

Expand Down
Loading
Loading