Skip to content

Commit

Permalink
lib,mgmtd: Add support for GETDATA_REQ on Operational DB
Browse files Browse the repository at this point in the history
Handle GETDATA_REQ from Front-end clients and retrieve data fron
backend clients

Co-authored-by: Yash Ranjan <[email protected]>
Signed-off-by: Pushpasis Sarkar <[email protected]>
  • Loading branch information
pushpasis and YashRanjanVMWare committed Sep 25, 2023
1 parent d9d08e2 commit 7cb6b12
Show file tree
Hide file tree
Showing 14 changed files with 1,880 additions and 314 deletions.
375 changes: 363 additions & 12 deletions lib/mgmt_be_client.c

Large diffs are not rendered by default.

18 changes: 11 additions & 7 deletions lib/mgmt_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,11 @@ int mgmt_xpath_find_first_wildcard(const char *xpath, int *key_end)
* Resolve wildcard entry in a given xpath.
*/
int mgmt_xpath_resolve_wildcard(char *xpath, int start_indx,
void (*get_child_fn)(char *base_xpath,
const char *child_xpath[],
void *child_ctxt[],
int *num_child,
void *ctxt, char* xpath_key),
int (*get_child_fn)(const char *base_xpath,
const char *child_xpath[],
void *child_ctxt[],
int *num_child,
void *ctxt, char *xpath_key),
int (*iter_fn)(const char *child_xpath,
void *child_ctxt,
void *ctxt),
Expand Down Expand Up @@ -336,8 +336,12 @@ int mgmt_xpath_resolve_wildcard(char *xpath, int start_indx,
xpath[start_indx + wc_key_start - 1] = '\0';
}
num_child = array_size(chld_xpath);
(*get_child_fn)(xpath, (const char**)chld_xpath, chld_ctxt,
&num_child, ctxt, xpath_key);
ret = (*get_child_fn)(xpath, (const char **)chld_xpath, chld_ctxt,
&num_child, ctxt, xpath_key);
if (ret) {
MGMTD_UTIL_DBG("Value of get child function %d", ret);
return ret;
}
if (wc_key_start >= 0)
xpath[start_indx + wc_key_start - 1] = orig;

Expand Down
10 changes: 5 additions & 5 deletions lib/mgmt_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,11 @@ extern int mgmt_xpath_find_first_wildcard(const char *xpath, int *key_end);
* recursive resolution level.
*/
extern int mgmt_xpath_resolve_wildcard(char *xpath, int start_indx,
void (*get_child_fn)(char *base_xpath,
const char *child_xpath[],
void *child_ctxt[],
int *num_child,
void *ctxt, char* xpath_key),
int (*get_child_fn)(const char *base_xpath,
const char *child_xpath[],
void *child_ctxt[],
int *num_child,
void *ctxt, char *xpath_key),
int (*iter_fn)(const char *child_xpath,
void *child_ctxt,
void *ctxt),
Expand Down
221 changes: 172 additions & 49 deletions lib/northbound.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,6 @@ static int nb_transaction_process(enum nb_event event,
char *errmsg, size_t errmsg_len);
static void nb_transaction_apply_finish(struct nb_transaction *transaction,
char *errmsg, size_t errmsg_len);
static int nb_oper_data_iter_node(const struct lysc_node *snode,
const char *xpath, const void *list_entry,
const struct yang_list_keys *list_keys,
struct yang_translator *translator,
bool first, uint32_t flags,
nb_oper_data_cb cb, void *arg);

static int nb_node_check_config_only(const struct lysc_node *snode, void *arg)
{
Expand Down Expand Up @@ -1833,12 +1827,15 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction,
}
}

static int nb_oper_data_iter_children(const struct lysc_node *snode,
const char *xpath, const void *list_entry,
const struct yang_list_keys *list_keys,
struct yang_translator *translator,
bool first, uint32_t flags,
nb_oper_data_cb cb, void *arg)
/*
* API to iterate over child nodes.
*/
int nb_oper_data_iter_children(const struct lysc_node *snode,
const char *xpath, const void *list_entry,
const struct yang_list_keys *list_keys,
struct yang_translator *translator,
bool first, uint32_t flags,
nb_oper_data_cb cb, void *arg)
{
const struct lysc_node *child;

Expand Down Expand Up @@ -1866,6 +1863,9 @@ static int nb_oper_data_iter_leaf(const struct nb_node *nb_node,
if (CHECK_FLAG(nb_node->snode->flags, LYS_CONFIG_W))
return NB_OK;

if (CHECK_FLAG(flags, NB_OPER_DATA_ITER_SKIPLEAFS))
return NB_OK;

/* Ignore list keys. */
if (lysc_is_key(nb_node->snode))
return NB_OK;
Expand Down Expand Up @@ -2015,6 +2015,15 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node,
position++;
}

if (CHECK_FLAG(flags, NB_OPER_DATA_ITER_VISITLISTKEYS)) {
struct yang_data data = { 0 };

strlcpy(data.xpath, xpath, sizeof(data.xpath));
ret = (*cb)(nb_node->snode, translator, &data, arg);

continue;
}

/* Iterate over the child nodes. */
ret = nb_oper_data_iter_children(
nb_node->snode, xpath, list_entry, &list_keys,
Expand All @@ -2026,13 +2035,16 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node,
return NB_OK;
}

static int nb_oper_data_iter_node(const struct lysc_node *snode,
const char *xpath_parent,
const void *list_entry,
const struct yang_list_keys *list_keys,
struct yang_translator *translator,
bool first, uint32_t flags,
nb_oper_data_cb cb, void *arg)
/*
* Iterate over operational data for a particular node.
*/
int nb_oper_data_iter_node(const struct lysc_node *snode,
const char *xpath_parent,
const void *list_entry,
const struct yang_list_keys *list_keys,
struct yang_translator *translator,
bool first, uint32_t flags,
nb_oper_data_cb cb, void *arg)
{
struct nb_node *nb_node;
char xpath[XPATH_MAXLEN];
Expand Down Expand Up @@ -2098,31 +2110,29 @@ static int nb_oper_data_iter_node(const struct lysc_node *snode,
return ret;
}

int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
uint32_t flags, nb_oper_data_cb cb, void *arg)
/*
* Iterarte over the to find the particular list entry.
*/
const void *nb_oper_get_list_entry(const char *xpath,
struct nb_node *nb_node,
struct lyd_node **pdnode,
struct yang_list_keys *list_keys)
{
struct nb_node *nb_node;
const void *list_entry = NULL;
struct yang_list_keys list_keys;
struct list *list_dnodes;
struct lyd_node *dnode, *dn;
struct listnode *ln;
int ret;
struct list *list_dnodes;

zlog_debug("%s: start xpath %s", __func__, xpath);
*pdnode = NULL;

if (!nb_node)
nb_node = nb_node_find(xpath);

nb_node = nb_node_find(xpath);
if (!nb_node) {
flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
"%s: unknown data path: %s", __func__, xpath);
return NB_ERR;
}

/* For now this function works only with containers and lists. */
if (!CHECK_FLAG(nb_node->snode->nodetype, LYS_CONTAINER | LYS_LIST)) {
flog_warn(
EC_LIB_NB_OPERATIONAL_DATA,
"%s: can't iterate over YANG leaf or leaf-list [xpath %s]",
__func__, xpath);
return NB_ERR;
return NULL;
}

/*
Expand All @@ -2131,13 +2141,13 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
*/

LY_ERR err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0,
LYD_NEW_PATH_UPDATE, NULL, &dnode);
LYD_NEW_PATH_UPDATE, NULL, &dnode);
if (err || !dnode) {
const char *errmsg =
err ? ly_errmsg(ly_native_ctx) : "node not found";
flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed %s",
__func__, errmsg);
return NB_ERR;
return NULL;
}

/*
Expand All @@ -2149,6 +2159,7 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
continue;
listnode_add_head(list_dnodes, dn);
}

/*
* Use the northbound callbacks to find list entry pointer corresponding
* to the given XPath.
Expand All @@ -2159,20 +2170,21 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
unsigned int n = 0;

/* Obtain the list entry keys. */
memset(&list_keys, 0, sizeof(list_keys));
memset(list_keys, 0, sizeof(*list_keys));
LY_LIST_FOR (lyd_child(dn), child) {
if (!lysc_is_key(child->schema))
break;
strlcpy(list_keys.key[n],
strlcpy(list_keys->key[n],
yang_dnode_get_string(child, NULL),
sizeof(list_keys.key[n]));
sizeof(list_keys->key[n]));
n++;
}
list_keys.num = n;
if (list_keys.num != yang_snode_num_keys(dn->schema)) {
list_keys->num = n;

if (list_keys->num != yang_snode_num_keys(dn->schema)) {
list_delete(&list_dnodes);
yang_dnode_free(dnode);
return NB_ERR_NOT_FOUND;
return NULL;
}

/* Find the list entry pointer. */
Expand All @@ -2184,18 +2196,127 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
__func__, xpath);
list_delete(&list_dnodes);
yang_dnode_free(dnode);
return NB_ERR;
return NULL;
}

list_entry =
nb_callback_lookup_entry(nn, list_entry, &list_keys);
nb_callback_lookup_entry(nn, list_entry, list_keys);
if (list_entry == NULL) {
list_delete(&list_dnodes);
yang_dnode_free(dnode);
return NB_ERR_NOT_FOUND;
return NULL;
}
}

*pdnode = dnode;
zlog_debug("%s: List-entry for '%s' --> %p",
__func__, nb_node->snode->name, list_entry);
return list_entry;
}

/*
* API to iterarte over the nb tree to find the data node
* for nb_node, for a given xpath.
*/
static int nb_oper_data_walk_elem(const char *xpath,
struct nb_node *nb_node,
struct yang_translator *translator,
uint32_t flags, nb_oper_data_cb cb,
void *arg)
{
const void *list_entry = NULL;
struct yang_list_keys list_keys;
struct lyd_node *dnode = NULL;
char *pos, *elem;
int ret = NB_OK;

if (!nb_node)
nb_node = nb_node_find(xpath);

if (!nb_node) {
flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
"%s: unknown data path: %s", __func__, xpath);
ret = NB_ERR;
goto nb_oper_data_walk_elem_done;
}

/* For now this function works only with containers and lists. */
if (CHECK_FLAG(nb_node->snode->nodetype, LYS_CONTAINER | LYS_LIST)) {
flog_warn(
EC_LIB_NB_OPERATIONAL_DATA,
"%s: can't iterate a container or list [xpath %s]",
__func__, xpath);
ret = NB_ERR;
goto nb_oper_data_walk_elem_done;
}

pos = strrchr(xpath, '/');
if (pos) {
*pos = '\0';
elem = pos + 1;
list_entry =
nb_oper_get_list_entry(xpath, NULL, &dnode,
&list_keys);
*pos = '/';
if (!dnode) {
zlog_debug("%s: Did not get dnode for nb_node '%s'",
__func__, nb_node->snode->name);
ret = NB_ERR_NOT_FOUND;
goto nb_oper_data_walk_elem_done;
} else {
zlog_debug("%s: Parent list %p found for nb_node %p ('%s'/'%s')",
__func__, list_entry, nb_node, nb_node->snode->name, elem);
}
}

ret = nb_oper_data_iter_leaf(nb_node, xpath, list_entry, &list_keys,
translator, flags, cb, arg);

nb_oper_data_walk_elem_done:
if (dnode)
yang_dnode_free(dnode);

return ret;
}

/*
* Iterate over operational data.
*/
int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
uint32_t flags, nb_oper_data_cb cb, void *arg)
{
struct nb_node *nb_node;
const void *list_entry = NULL;
struct yang_list_keys list_keys;
struct lyd_node *dnode = NULL;
int ret;

zlog_debug("%s: start xpath %s", __func__, xpath);
nb_node = nb_node_find(xpath);
if (!nb_node) {
flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
"%s: unknown data path: %s", __func__, xpath);
return NB_ERR;
}

/* For leaf nodes we need a different processing. */
if (!CHECK_FLAG(nb_node->snode->nodetype, LYS_CONTAINER | LYS_LIST)) {
return nb_oper_data_walk_elem(
xpath, nb_node, translator, flags, cb, arg);
}

list_entry =
nb_oper_get_list_entry(xpath, nb_node, &dnode, &list_keys);
if (!dnode) {
zlog_debug("%s: Did not get dnode for nb_node '%s'",
__func__, nb_node->snode->name);
ret = NB_ERR_NOT_FOUND;
goto nb_oper_data_iterate_done;
} else {
zlog_debug("%s: Parent list %p found for nb_node %p ('%s')",
__func__, list_entry, nb_node, nb_node->snode->name);
}

/* If a list entry was given, iterate over that list entry only. */
if (dnode->schema->nodetype == LYS_LIST && lyd_child(dnode))
ret = nb_oper_data_iter_children(
Expand All @@ -2206,8 +2327,10 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
&list_keys, translator, true,
flags, cb, arg);

list_delete(&list_dnodes);
yang_dnode_free(dnode);
nb_oper_data_iterate_done:

if (dnode)
yang_dnode_free(dnode);

return ret;
}
Expand Down
Loading

0 comments on commit 7cb6b12

Please sign in to comment.