valid = nb_operation_is_valid(operation, nb_node->snode);
- if (!valid && callback_implemented)
+ /*
+ * Add an exception for operational data callbacks. A rw list usually
+ * doesn't need any associated operational data callbacks. But if this
+ * rw list is augmented by another module which adds state nodes under
+ * it, then this list will need to have the 'get_next()', 'get_keys()'
+ * and 'lookup_entry()' callbacks. As such, never log a warning when
+ * these callbacks are implemented when they are not needed, since this
+ * depends on context (e.g. some daemons might augment "frr-interface"
+ * while others don't).
+ */
+ if (!valid && callback_implemented && operation != NB_OP_GET_NEXT
+ && operation != NB_OP_GET_KEYS && operation != NB_OP_LOOKUP_ENTRY)
flog_warn(EC_LIB_NB_CB_UNNEEDED,
"unneeded '%s' callback for '%s'",
nb_operation_name(operation), nb_node->xpath);
/*
* Preserve the order of the configuration changes as told by libyang.
*/
- return a->seq - b->seq;
+ if (a->seq < b->seq)
+ return -1;
+ if (a->seq > b->seq)
+ return 1;
+
+ /*
+ * All 'apply_finish' callbacks have their sequence number set to zero.
+ * In this case, compare them using their dnode pointers (the order
+ * doesn't matter for callbacks that have the same priority).
+ */
+ if (a->dnode < b->dnode)
+ return -1;
+ if (a->dnode > b->dnode)
+ return 1;
+
+ return 0;
}
RB_GENERATE(nb_config_cbs, nb_config_cb, entry, nb_config_cb_compare);
change->cb.seq = *seq;
*seq = *seq + 1;
change->cb.nb_node = dnode->schema->priv;
- yang_dnode_get_path(dnode, change->cb.xpath, sizeof(change->cb.xpath));
change->cb.dnode = dnode;
RB_INSERT(nb_config_cbs, changes, &change->cb);
__func__);
return NB_ERR;
}
-
- /*
- * If a new node was created, call lyd_validate() only to create
- * default child nodes.
- */
- if (dnode) {
- lyd_schema_sort(dnode, 0);
- lyd_validate(&dnode,
- LYD_OPT_CONFIG | LYD_OPT_WHENAUTODEL,
- ly_native_ctx);
- }
break;
case NB_OP_DESTROY:
dnode = yang_dnode_get(candidate->dnode, xpath_edit);
struct nb_config_change *change)
{
enum nb_operation operation = change->cb.operation;
- const char *xpath = change->cb.xpath;
+ char xpath[XPATH_MAXLEN];
const struct nb_node *nb_node = change->cb.nb_node;
const struct lyd_node *dnode = change->cb.dnode;
union nb_resource *resource;
if (dnode && !yang_snode_is_typeless_data(dnode->schema))
value = yang_dnode_get_string(dnode, NULL);
+ yang_dnode_get_path(dnode, xpath, sizeof(xpath));
nb_log_callback(event, operation, xpath, value);
}
ret = (*nb_node->cbs.move)(event, dnode);
break;
default:
+ yang_dnode_get_path(dnode, xpath, sizeof(xpath));
flog_err(EC_LIB_DEVELOPMENT,
"%s: unknown operation (%u) [xpath %s]", __func__,
operation, xpath);
int priority;
enum lib_log_refs ref;
+ yang_dnode_get_path(dnode, xpath, sizeof(xpath));
+
switch (event) {
case NB_EV_VALIDATE:
priority = LOG_WARNING;
}
static struct nb_config_cb *
-nb_apply_finish_cb_new(struct nb_config_cbs *cbs, const char *xpath,
- const struct nb_node *nb_node,
+nb_apply_finish_cb_new(struct nb_config_cbs *cbs, const struct nb_node *nb_node,
const struct lyd_node *dnode)
{
struct nb_config_cb *cb;
cb = XCALLOC(MTYPE_TMP, sizeof(*cb));
- strlcpy(cb->xpath, xpath, sizeof(cb->xpath));
cb->nb_node = nb_node;
cb->dnode = dnode;
RB_INSERT(nb_config_cbs, cbs, cb);
}
static struct nb_config_cb *
-nb_apply_finish_cb_find(struct nb_config_cbs *cbs, const char *xpath,
- const struct nb_node *nb_node)
+nb_apply_finish_cb_find(struct nb_config_cbs *cbs,
+ const struct nb_node *nb_node,
+ const struct lyd_node *dnode)
{
struct nb_config_cb s;
- strlcpy(s.xpath, xpath, sizeof(s.xpath));
+ s.seq = 0;
s.nb_node = nb_node;
+ s.dnode = dnode;
return RB_FIND(nb_config_cbs, cbs, &s);
}
{
struct nb_config_cbs cbs;
struct nb_config_cb *cb;
+ char xpath[XPATH_MAXLEN];
/* Initialize tree of 'apply_finish' callbacks. */
RB_INIT(nb_config_cbs, &cbs);
* be called though).
*/
if (change->cb.operation == NB_OP_DESTROY) {
- char xpath[XPATH_MAXLEN];
-
dnode = dnode->parent;
if (!dnode)
break;
xpath);
}
while (dnode) {
- char xpath[XPATH_MAXLEN];
struct nb_node *nb_node;
nb_node = dnode->schema->priv;
* Don't call the callback more than once for the same
* data node.
*/
- yang_dnode_get_path(dnode, xpath, sizeof(xpath));
- if (nb_apply_finish_cb_find(&cbs, xpath, nb_node))
+ if (nb_apply_finish_cb_find(&cbs, nb_node, dnode))
goto next;
- nb_apply_finish_cb_new(&cbs, xpath, nb_node, dnode);
+ nb_apply_finish_cb_new(&cbs, nb_node, dnode);
next:
dnode = dnode->parent;
/* Call the 'apply_finish' callbacks, sorted by their priorities. */
RB_FOREACH (cb, nb_config_cbs, &cbs) {
- if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL))
- nb_log_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH,
- cb->xpath, NULL);
+ if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) {
+ yang_dnode_get_path(cb->dnode, xpath, sizeof(xpath));
+ nb_log_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH, xpath,
+ NULL);
+ }
(*cb->nb_node->cbs.apply_finish)(cb->dnode);
}
}
void nb_init(struct thread_master *tm,
- const struct frr_yang_module_info *modules[], size_t nmodules)
+ const struct frr_yang_module_info *const modules[],
+ size_t nmodules)
{
unsigned int errors = 0;