if (config_only)
SET_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY);
}
+ if (CHECK_FLAG(snode->nodetype, LYS_LIST)) {
+ struct lys_node_list *slist;
+
+ slist = (struct lys_node_list *)snode;
+ if (slist->keys_size == 0)
+ SET_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST);
+ }
/*
* Link the northbound node and the libyang schema node with one
const struct lyd_node *dnode = change->cb.dnode;
union nb_resource *resource;
int ret = NB_ERR;
+ enum lib_log_refs ref;
if (debug_northbound) {
const char *value = "(none)";
break;
}
- if (ret != NB_OK)
- flog_warn(
- EC_LIB_NB_CB_CONFIG,
- "%s: error processing configuration change: error [%s] event [%s] operation [%s] xpath [%s]",
- __func__, nb_err_name(ret), nb_event_name(event),
- nb_operation_name(operation), xpath);
+ if (ret != NB_OK) {
+ switch (event) {
+ case NB_EV_VALIDATE:
+ ref = EC_LIB_NB_CB_CONFIG_VALIDATE;
+ break;
+ case NB_EV_PREPARE:
+ ref = EC_LIB_NB_CB_CONFIG_PREPARE;
+ break;
+ case NB_EV_ABORT:
+ ref = EC_LIB_NB_CB_CONFIG_ABORT;
+ break;
+ case NB_EV_APPLY:
+ ref = EC_LIB_NB_CB_CONFIG_APPLY;
+ break;
+ }
+ if (event == NB_EV_VALIDATE || event == NB_EV_PREPARE)
+ flog_warn(
+ ref,
+ "%s: error processing configuration change: error [%s] event [%s] operation [%s] xpath [%s]",
+ __func__, nb_err_name(ret),
+ nb_event_name(event),
+ nb_operation_name(operation), xpath);
+ else
+ flog_err(
+ ref,
+ "%s: error processing configuration change: error [%s] event [%s] operation [%s] xpath [%s]",
+ __func__, nb_err_name(ret),
+ nb_event_name(event),
+ nb_operation_name(operation), xpath);
+ }
return ret;
}
{
struct lys_node_list *slist = (struct lys_node_list *)nb_node->snode;
const void *list_entry = NULL;
+ uint32_t position = 1;
if (CHECK_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY))
return NB_OK;
/* Iterate over all list entries. */
do {
struct yang_list_keys list_keys;
- char xpath[XPATH_MAXLEN];
+ char xpath[XPATH_MAXLEN * 2];
int ret;
/* Obtain list entry. */
/* End of the list. */
break;
- /* Obtain the list entry keys. */
- if (nb_node->cbs.get_keys(list_entry, &list_keys) != NB_OK) {
- flog_warn(EC_LIB_NB_CB_STATE,
- "%s: failed to get list keys", __func__);
- return NB_ERR;
- }
-
- /* Build XPath of the list entry. */
- strlcpy(xpath, xpath_list, sizeof(xpath));
- for (unsigned int i = 0; i < list_keys.num; i++) {
- snprintf(xpath + strlen(xpath),
- sizeof(xpath) - strlen(xpath), "[%s='%s']",
- slist->keys[i]->name, list_keys.key[i]);
+ if (!CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST)) {
+ /* Obtain the list entry keys. */
+ if (nb_node->cbs.get_keys(list_entry, &list_keys)
+ != NB_OK) {
+ flog_warn(EC_LIB_NB_CB_STATE,
+ "%s: failed to get list keys",
+ __func__);
+ return NB_ERR;
+ }
+
+ /* Build XPath of the list entry. */
+ strlcpy(xpath, xpath_list, sizeof(xpath));
+ for (unsigned int i = 0; i < list_keys.num; i++) {
+ snprintf(xpath + strlen(xpath),
+ sizeof(xpath) - strlen(xpath),
+ "[%s='%s']", slist->keys[i]->name,
+ list_keys.key[i]);
+ }
+ } else {
+ /*
+ * Keyless list - build XPath using a positional index.
+ */
+ snprintf(xpath, sizeof(xpath), "%s[%u]", xpath_list,
+ position);
+ position++;
}
/* Iterate over the child nodes. */
case LYS_LIST:
if (CHECK_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY))
return false;
+ if (CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST))
+ return false;
break;
default:
return false;