]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/northbound.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / lib / northbound.c
index 8503f87d608c5a32783c419e8d9fe8f0aa9a0f42..a7f9c8620ef9e57c5fa1331bca35471e2023bc0a 100644 (file)
@@ -95,6 +95,13 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg)
                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
@@ -712,6 +719,7 @@ static int nb_configuration_callback(const enum nb_event event,
        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)";
@@ -744,12 +752,36 @@ static int nb_configuration_callback(const enum nb_event event,
                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;
 }
@@ -1056,6 +1088,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node,
 {
        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;
@@ -1063,7 +1096,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node,
        /* 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. */
@@ -1073,19 +1106,31 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node,
                        /* 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. */
@@ -1400,6 +1445,8 @@ bool nb_operation_is_valid(enum nb_operation operation,
                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;