summaryrefslogtreecommitdiff
path: root/lib/northbound_sysrepo.c
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2018-11-02 22:16:55 -0200
committerRenato Westphal <renato@opensourcerouting.org>2018-11-26 18:28:53 -0200
commit1a4bc045deac52e5c0b66d151dbbce8cc3675497 (patch)
treefa244f4c2f65da6f20bc8b44dd78315483e47bce /lib/northbound_sysrepo.c
parent85cd3326fd4fd424e17c964255d18f3803369e05 (diff)
lib, tests: major rework in the operational-data callbacks
The northbound infrastructure for operational data was subpar compared to the infrastructure for configuration data. This commit addresses most of the existing problems, making it possible to write operational-data callbacks for more complex YANG models. Summary of the changes: * Add support for nested YANG lists. * Add support for leaf-lists. * Add support for leafs of type "empty". * Introduce the "show yang operational-data XPATH" command, and write an unit test for it. The main purpose of this command is to make it easier to test the operational-data northbound callbacks. * Introduce the nb_oper_data_iterate() function, that can be used to iterate over operational data. Make the CLI and sysrepo use this function. * Since ConfD has a very peculiar API, it can't reuse the nb_oper_data_iterate() like the other northbound clients. In this case, adapt the existing ConfD callbacks to support the new features (and make some performance improvements in the process). Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'lib/northbound_sysrepo.c')
-rw-r--r--lib/northbound_sysrepo.c130
1 files changed, 14 insertions, 116 deletions
diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c
index 9c07db8560..ffda4c65d0 100644
--- a/lib/northbound_sysrepo.c
+++ b/lib/northbound_sysrepo.c
@@ -299,111 +299,15 @@ static int frr_sr_config_change_cb(sr_session_ctx_t *session,
}
}
-static void frr_sr_state_get_elem(struct list *elements,
- struct nb_node *nb_node,
- const void *list_entry, const char *xpath)
+static int frr_sr_state_data_iter_cb(const struct lys_node *snode,
+ struct yang_translator *translator,
+ struct yang_data *data, void *arg)
{
- struct yang_data *data;
-
- data = nb_node->cbs.get_elem(xpath, list_entry);
- if (data)
- listnode_add(elements, data);
-}
-
-static void frr_sr_state_cb_container(struct list *elements, const char *xpath,
- const struct lys_node *snode)
-{
- struct lys_node *child;
-
- LY_TREE_FOR (snode->child, child) {
- struct nb_node *nb_node = child->priv;
- char xpath_child[XPATH_MAXLEN];
-
- if (!nb_operation_is_valid(NB_OP_GET_ELEM, child))
- continue;
-
- snprintf(xpath_child, sizeof(xpath_child), "%s/%s", xpath,
- child->name);
-
- frr_sr_state_get_elem(elements, nb_node, NULL, xpath_child);
- }
-}
-
-static void frr_sr_state_cb_list_entry(struct list *elements,
- const char *xpath_list,
- const void *list_entry,
- struct lys_node *child)
-{
- struct nb_node *nb_node = child->priv;
- struct lys_node_leaf *sleaf;
- char xpath_child[XPATH_MAXLEN];
-
- /* Sysrepo doesn't want to know about list keys. */
- switch (child->nodetype) {
- case LYS_LEAF:
- sleaf = (struct lys_node_leaf *)child;
- if (lys_is_key(sleaf, NULL))
- return;
- break;
- case LYS_LEAFLIST:
- break;
- default:
- return;
- }
-
- if (!nb_operation_is_valid(NB_OP_GET_ELEM, child))
- return;
-
- snprintf(xpath_child, sizeof(xpath_child), "%s/%s", xpath_list,
- child->name);
+ struct list *elements = arg;
- frr_sr_state_get_elem(elements, nb_node, list_entry, xpath_child);
-}
+ listnode_add(elements, data);
-static void frr_sr_state_cb_list(struct list *elements, const char *xpath,
- const struct lys_node *snode)
-{
- struct nb_node *nb_node = snode->priv;
- struct lys_node_list *slist = (struct lys_node_list *)snode;
- const void *next;
-
- for (next = nb_node->cbs.get_next(xpath, NULL); next;
- next = nb_node->cbs.get_next(xpath, next)) {
- struct yang_list_keys keys;
- const void *list_entry;
- char xpath_list[XPATH_MAXLEN];
- struct lys_node *child;
-
- /* Get the list keys. */
- if (nb_node->cbs.get_keys(next, &keys) != NB_OK) {
- flog_warn(EC_LIB_NB_CB_STATE,
- "%s: failed to get list keys", __func__);
- continue;
- }
-
- /* Get list item. */
- list_entry = nb_node->cbs.lookup_entry(&keys);
- if (!list_entry) {
- flog_warn(EC_LIB_NB_CB_STATE,
- "%s: failed to lookup list entry", __func__);
- continue;
- }
-
- /* Append list keys to the XPath. */
- strlcpy(xpath_list, xpath, sizeof(xpath_list));
- for (unsigned int i = 0; i < keys.num; i++) {
- snprintf(xpath_list + strlen(xpath_list),
- sizeof(xpath_list) - strlen(xpath_list),
- "[%s='%s']", slist->keys[i]->name,
- keys.key[i]);
- }
-
- /* Loop through list entries. */
- LY_TREE_FOR (snode->child, child) {
- frr_sr_state_cb_list_entry(elements, xpath_list,
- list_entry, child);
- }
- }
+ return NB_OK;
}
/* Callback for state retrieval. */
@@ -413,26 +317,20 @@ static int frr_sr_state_cb(const char *xpath, sr_val_t **values,
{
struct list *elements;
struct yang_data *data;
- const struct lys_node *snode;
struct listnode *node;
sr_val_t *v;
int ret, count, i = 0;
- /* Find schema node. */
- snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0);
-
elements = yang_data_list_new();
-
- switch (snode->nodetype) {
- case LYS_CONTAINER:
- frr_sr_state_cb_container(elements, xpath, snode);
- break;
- case LYS_LIST:
- frr_sr_state_cb_list(elements, xpath, snode);
- break;
- default:
- break;
+ if (nb_oper_data_iterate(xpath, NULL, NB_OPER_DATA_ITER_NORECURSE,
+ frr_sr_state_data_iter_cb, elements)
+ != NB_OK) {
+ flog_warn(EC_LIB_NB_OPERATIONAL_DATA,
+ "%s: failed to obtain operational data [xpath %s]",
+ __func__, xpath);
+ goto exit;
}
+
if (list_isempty(elements))
goto exit;