2 * Copyright (C) 2018 NetDEF, Inc.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #ifndef _FRR_NORTHBOUND_H_
21 #define _FRR_NORTHBOUND_H_
26 #include "openbsd-tree.h"
28 #include "yang_translator.h"
34 /* Forward declaration(s). */
38 /* Northbound events. */
41 * The configuration callback is supposed to verify that the changes are
42 * valid and can be applied.
47 * The configuration callback is supposed to prepare all resources
48 * required to apply the changes.
53 * Transaction has failed, the configuration callback needs to release
54 * all resources previously allocated.
59 * The configuration changes need to be applied. The changes can't be
60 * rejected at this point (errors are logged and ignored).
66 * Northbound operations.
68 * Refer to the documentation comments of nb_callbacks for more details.
90 * Configuration callback.
92 * A presence container, list entry, leaf-list entry or leaf of type
93 * empty has been created.
95 * For presence-containers and list entries, the callback is supposed to
96 * initialize the default values of its children (if any) from the YANG
100 * The transaction phase. Refer to the documentation comments of
101 * nb_event for more details.
104 * libyang data node that is being created.
107 * Pointer to store resource(s) allocated during the NB_EV_PREPARE
108 * phase. The same pointer can be used during the NB_EV_ABORT and
109 * NB_EV_APPLY phases to either release or make use of the allocated
110 * resource(s). It's set to NULL when the event is NB_EV_VALIDATE.
113 * - NB_OK on success.
114 * - NB_ERR_VALIDATION when a validation error occurred.
115 * - NB_ERR_RESOURCE when the callback failed to allocate a resource.
116 * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
117 * - NB_ERR for other errors.
119 int (*create
)(enum nb_event event
, const struct lyd_node
*dnode
,
120 union nb_resource
*resource
);
123 * Configuration callback.
125 * The value of a leaf has been modified.
127 * List keys don't need to implement this callback. When a list key is
128 * modified, the northbound treats this as if the list was deleted and a
129 * new one created with the updated key value.
132 * The transaction phase. Refer to the documentation comments of
133 * nb_event for more details.
136 * libyang data node that is being modified
139 * Pointer to store resource(s) allocated during the NB_EV_PREPARE
140 * phase. The same pointer can be used during the NB_EV_ABORT and
141 * NB_EV_APPLY phases to either release or make use of the allocated
142 * resource(s). It's set to NULL when the event is NB_EV_VALIDATE.
145 * - NB_OK on success.
146 * - NB_ERR_VALIDATION when a validation error occurred.
147 * - NB_ERR_RESOURCE when the callback failed to allocate a resource.
148 * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
149 * - NB_ERR for other errors.
151 int (*modify
)(enum nb_event event
, const struct lyd_node
*dnode
,
152 union nb_resource
*resource
);
155 * Configuration callback.
157 * A presence container, list entry, leaf-list entry or optional leaf
160 * The callback is supposed to delete the entire configuration object,
161 * including its children when they exist.
164 * The transaction phase. Refer to the documentation comments of
165 * nb_event for more details.
168 * libyang data node that is being deleted.
171 * - NB_OK on success.
172 * - NB_ERR_VALIDATION when a validation error occurred.
173 * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
174 * - NB_ERR for other errors.
176 int (*destroy
)(enum nb_event event
, const struct lyd_node
*dnode
);
179 * Configuration callback.
181 * A list entry or leaf-list entry has been moved. Only applicable when
182 * the "ordered-by user" statement is present.
185 * The transaction phase. Refer to the documentation comments of
186 * nb_event for more details.
189 * libyang data node that is being moved.
192 * - NB_OK on success.
193 * - NB_ERR_VALIDATION when a validation error occurred.
194 * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
195 * - NB_ERR for other errors.
197 int (*move
)(enum nb_event event
, const struct lyd_node
*dnode
);
200 * Optional configuration callback.
202 * The 'apply_finish' callbacks are called after all other callbacks
203 * during the apply phase (NB_EV_APPLY). These callbacks are called only
204 * under one of the following two cases:
205 * - The data node has been created or modified (but not deleted);
206 * - Any change was made within the descendants of the data node (e.g. a
207 * child leaf was modified, created or deleted).
209 * In the second case above, the 'apply_finish' callback is called only
210 * once even if multiple changes occurred within the descendants of the
214 * libyang data node associated with the 'apply_finish' callback.
216 void (*apply_finish
)(const struct lyd_node
*dnode
);
219 * Operational data callback.
221 * The callback function should return the value of a specific leaf,
222 * leaf-list entry or inform if a typeless value (presence containers or
223 * leafs of type empty) exists or not.
226 * YANG data path of the data we want to get.
229 * Pointer to list entry (might be NULL).
232 * Pointer to newly created yang_data structure, or NULL to indicate
233 * the absence of data.
235 struct yang_data
*(*get_elem
)(const char *xpath
,
236 const void *list_entry
);
239 * Operational data callback for YANG lists and leaf-lists.
241 * The callback function should return the next entry in the list or
242 * leaf-list. The 'list_entry' parameter will be NULL on the first
246 * Pointer to parent list entry.
249 * Pointer to (leaf-)list entry.
252 * Pointer to the next entry in the (leaf-)list, or NULL to signal
253 * that the end of the (leaf-)list was reached.
255 const void *(*get_next
)(const void *parent_list_entry
,
256 const void *list_entry
);
259 * Operational data callback for YANG lists.
261 * The callback function should fill the 'keys' parameter based on the
262 * given list_entry. Keyless lists don't need to implement this
266 * Pointer to list entry.
269 * Structure to be filled based on the attributes of the provided
273 * NB_OK on success, NB_ERR otherwise.
275 int (*get_keys
)(const void *list_entry
, struct yang_list_keys
*keys
);
278 * Operational data callback for YANG lists.
280 * The callback function should return a list entry based on the list
281 * keys given as a parameter. Keyless lists don't need to implement this
285 * Pointer to parent list entry.
288 * Structure containing the keys of the list entry.
291 * Pointer to the list entry if found, or NULL if not found.
293 const void *(*lookup_entry
)(const void *parent_list_entry
,
294 const struct yang_list_keys
*keys
);
297 * RPC and action callback.
299 * Both 'input' and 'output' are lists of 'yang_data' structures. The
300 * callback should fetch all the input parameters from the 'input' list,
301 * and add output parameters to the 'output' list if necessary.
304 * XPath of the YANG RPC or action.
307 * Read-only list of input parameters.
310 * List of output parameters to be populated by the callback.
313 * NB_OK on success, NB_ERR otherwise.
315 int (*rpc
)(const char *xpath
, const struct list
*input
,
316 struct list
*output
);
319 * Optional callback to show the CLI command associated to the given
323 * The vty terminal to dump the configuration to.
326 * libyang data node that should be shown in the form of a CLI
330 * Specify whether to display default configuration values or not.
331 * This parameter can be ignored most of the time since the
332 * northbound doesn't call this callback for default leaves or
333 * non-presence containers that contain only default child nodes.
334 * The exception are commands associated to multiple configuration
335 * nodes, in which case it might be desirable to hide one or more
336 * parts of the command when this parameter is set to false.
338 void (*cli_show
)(struct vty
*vty
, struct lyd_node
*dnode
,
343 * Northbound-specific data that is allocated for each schema node of the native
347 /* Back pointer to the libyang schema node. */
348 const struct lys_node
*snode
;
350 /* Data path of this YANG node. */
351 char xpath
[XPATH_MAXLEN
];
353 /* Priority - lower priorities are processed first. */
356 /* Callbacks implemented for this node. */
357 struct nb_callbacks cbs
;
360 * Pointer to the parent node (disconsidering non-presence containers).
362 struct nb_node
*parent
;
364 /* Pointer to the nearest parent list, if any. */
365 struct nb_node
*parent_list
;
371 /* ConfD hash value corresponding to this YANG path. */
375 /* The YANG container or list contains only config data. */
376 #define F_NB_NODE_CONFIG_ONLY 0x01
377 /* The YANG list doesn't contain key leafs. */
378 #define F_NB_NODE_KEYLESS_LIST 0x02
380 struct frr_yang_module_info
{
381 /* YANG module name. */
384 /* Northbound callbacks. */
386 /* Data path of this YANG node. */
389 /* Callbacks implemented for this node. */
390 struct nb_callbacks cbs
;
392 /* Priority - lower priorities are processed first. */
397 /* Northbound error codes. */
406 NB_ERR_INCONSISTENCY
,
409 /* Default priority. */
410 #define NB_DFLT_PRIORITY (UINT32_MAX / 2)
412 /* Default maximum of configuration rollbacks to store. */
413 #define NB_DLFT_MAX_CONFIG_ROLLBACKS 20
415 /* Northbound clients. */
424 /* Northbound configuration. */
426 /* Configuration data. */
427 struct lyd_node
*dnode
;
429 /* Configuration version. */
433 * Lock protecting this structure. The use of this lock is always
434 * necessary when reading or modifying the global running configuration.
435 * For candidate configurations, use of this lock is optional depending
436 * on the threading scheme of the northbound plugin.
438 pthread_rwlock_t lock
;
441 /* Northbound configuration callback. */
442 struct nb_config_cb
{
443 RB_ENTRY(nb_config_cb
) entry
;
444 enum nb_operation operation
;
445 char xpath
[XPATH_MAXLEN
];
446 const struct nb_node
*nb_node
;
447 const struct lyd_node
*dnode
;
449 RB_HEAD(nb_config_cbs
, nb_config_cb
);
450 RB_PROTOTYPE(nb_config_cbs
, nb_config_cb
, entry
, nb_config_cb_compare
);
452 /* Northbound configuration change. */
453 struct nb_config_change
{
454 struct nb_config_cb cb
;
455 union nb_resource resource
;
459 /* Northbound configuration transaction. */
460 struct nb_transaction
{
461 enum nb_client client
;
463 struct nb_config
*config
;
464 struct nb_config_cbs changes
;
467 /* Callback function used by nb_oper_data_iterate(). */
468 typedef int (*nb_oper_data_cb
)(const struct lys_node
*snode
,
469 struct yang_translator
*translator
,
470 struct yang_data
*data
, void *arg
);
472 /* Iterate over direct child nodes only. */
473 #define NB_OPER_DATA_ITER_NORECURSE 0x0001
476 DECLARE_HOOK(nb_notification_send
, (const char *xpath
, struct list
*arguments
),
478 DECLARE_HOOK(nb_client_debug_config_write
, (struct vty
*vty
), (vty
))
479 DECLARE_HOOK(nb_client_debug_set_all
, (uint32_t flags
, bool set
), (flags
, set
))
481 /* Northbound debugging records */
482 extern struct debug nb_dbg_cbs_config
;
483 extern struct debug nb_dbg_cbs_state
;
484 extern struct debug nb_dbg_cbs_rpc
;
485 extern struct debug nb_dbg_notif
;
486 extern struct debug nb_dbg_events
;
488 /* Global running configuration. */
489 extern struct nb_config
*running_config
;
491 /* Wrappers for the northbound callbacks. */
492 extern struct yang_data
*nb_callback_get_elem(const struct nb_node
*nb_node
,
494 const void *list_entry
);
495 extern const void *nb_callback_get_next(const struct nb_node
*nb_node
,
496 const void *parent_list_entry
,
497 const void *list_entry
);
498 extern int nb_callback_get_keys(const struct nb_node
*nb_node
,
499 const void *list_entry
,
500 struct yang_list_keys
*keys
);
501 extern const void *nb_callback_lookup_entry(const struct nb_node
*nb_node
,
502 const void *parent_list_entry
,
503 const struct yang_list_keys
*keys
);
504 extern int nb_callback_rpc(const struct nb_node
*nb_node
, const char *xpath
,
505 const struct list
*input
, struct list
*output
);
508 * Create a northbound node for all YANG schema nodes.
510 void nb_nodes_create(void);
513 * Delete all northbound nodes from all YANG schema nodes.
515 void nb_nodes_delete(void);
518 * Find the northbound node corresponding to a YANG data path.
521 * XPath to search for (with or without predicates).
524 * Pointer to northbound node if found, NULL otherwise.
526 extern struct nb_node
*nb_node_find(const char *xpath
);
529 * Create a new northbound configuration.
532 * Pointer to a libyang data node containing the configuration data. If NULL
533 * is given, an empty configuration will be created.
536 * Pointer to newly created northbound configuration.
538 extern struct nb_config
*nb_config_new(struct lyd_node
*dnode
);
541 * Delete a northbound configuration.
544 * Pointer to the config that is going to be deleted.
546 extern void nb_config_free(struct nb_config
*config
);
549 * Duplicate a northbound configuration.
552 * Northbound configuration to duplicate.
555 * Pointer to duplicated configuration.
557 extern struct nb_config
*nb_config_dup(const struct nb_config
*config
);
560 * Merge one configuration into another.
563 * Configuration to merge to.
566 * Configuration to merge config_dst with.
569 * Specify whether config_src should be deleted or not after the merge
573 * NB_OK on success, NB_ERR otherwise.
575 extern int nb_config_merge(struct nb_config
*config_dst
,
576 struct nb_config
*config_src
, bool preserve_source
);
579 * Replace one configuration by another.
582 * Configuration to be replaced.
585 * Configuration to replace config_dst.
588 * Specify whether config_src should be deleted or not after the replace
591 extern void nb_config_replace(struct nb_config
*config_dst
,
592 struct nb_config
*config_src
,
593 bool preserve_source
);
596 * Edit a candidate configuration.
599 * Candidate configuration to edit.
602 * Northbound node associated to the configuration being edited.
605 * Operation to apply.
608 * XPath of the configuration node being edited.
611 * Previous value of the configuration node. Should be used only when the
612 * operation is NB_OP_MOVE, otherwise this parameter is ignored.
615 * New value of the configuration node.
618 * - NB_OK on success.
619 * - NB_ERR_NOT_FOUND when the element to be deleted was not found.
620 * - NB_ERR for other errors.
622 extern int nb_candidate_edit(struct nb_config
*candidate
,
623 const struct nb_node
*nb_node
,
624 enum nb_operation operation
, const char *xpath
,
625 const struct yang_data
*previous
,
626 const struct yang_data
*data
);
629 * Check if a candidate configuration is outdated and needs to be updated.
632 * Candidate configuration to check.
635 * true if the candidate is outdated, false otherwise.
637 extern bool nb_candidate_needs_update(const struct nb_config
*candidate
);
640 * Update a candidate configuration by rebasing the changes on top of the latest
641 * running configuration. Resolve conflicts automatically by giving preference
642 * to the changes done in the candidate configuration.
645 * Candidate configuration to update.
648 * NB_OK on success, NB_ERR otherwise.
650 extern int nb_candidate_update(struct nb_config
*candidate
);
653 * Validate a candidate configuration. Perform both YANG syntactic/semantic
654 * validation and code-level validation using the northbound callbacks.
656 * WARNING: the candidate can be modified as part of the validation process
657 * (e.g. add default nodes).
660 * Candidate configuration to validate.
663 * NB_OK on success, NB_ERR_VALIDATION otherwise.
665 extern int nb_candidate_validate(struct nb_config
*candidate
);
668 * Create a new configuration transaction but do not commit it yet. Only
669 * validate the candidate and prepare all resources required to apply the
670 * configuration changes.
673 * Candidate configuration to commit.
676 * Northbound client performing the commit.
679 * Northbound user performing the commit (can be NULL).
682 * Optional comment describing the commit.
685 * Output parameter providing the created transaction when one is created
686 * successfully. In this case, it must be either aborted using
687 * nb_candidate_commit_abort() or committed using
688 * nb_candidate_commit_apply().
691 * - NB_OK on success.
692 * - NB_ERR_NO_CHANGES when the candidate is identical to the running
694 * - NB_ERR_LOCKED when there's already another transaction in progress.
695 * - NB_ERR_VALIDATION when the candidate fails the validation checks.
696 * - NB_ERR_RESOURCE when the system fails to allocate resources to apply
697 * the candidate configuration.
698 * - NB_ERR for other errors.
700 extern int nb_candidate_commit_prepare(struct nb_config
*candidate
,
701 enum nb_client client
, const void *user
,
703 struct nb_transaction
**transaction
);
706 * Abort a previously created configuration transaction, releasing all resources
707 * allocated during the preparation phase.
710 * Candidate configuration to abort. It's consumed by this function.
712 extern void nb_candidate_commit_abort(struct nb_transaction
*transaction
);
715 * Commit a previously created configuration transaction.
718 * Configuration transaction to commit. It's consumed by this function.
721 * Specify whether the transaction should be recorded in the transactions log
725 * Optional output parameter providing the ID of the committed transaction.
727 extern void nb_candidate_commit_apply(struct nb_transaction
*transaction
,
728 bool save_transaction
,
729 uint32_t *transaction_id
);
732 * Create a new transaction to commit a candidate configuration. This is a
733 * convenience function that performs the two-phase commit protocol
734 * transparently to the user. The cost is reduced flexibility, since
735 * network-wide and multi-daemon transactions require the network manager to
736 * take into account the results of the preparation phase of multiple managed
740 * Candidate configuration to commit. It's preserved regardless if the commit
741 * operation fails or not.
744 * Northbound client performing the commit.
747 * Northbound user performing the commit (can be NULL).
750 * Specify whether the transaction should be recorded in the transactions log
754 * Optional comment describing the commit.
757 * Optional output parameter providing the ID of the committed transaction.
760 * - NB_OK on success.
761 * - NB_ERR_NO_CHANGES when the candidate is identical to the running
763 * - NB_ERR_LOCKED when there's already another transaction in progress.
764 * - NB_ERR_VALIDATION when the candidate fails the validation checks.
765 * - NB_ERR_RESOURCE when the system fails to allocate resources to apply
766 * the candidate configuration.
767 * - NB_ERR for other errors.
769 extern int nb_candidate_commit(struct nb_config
*candidate
,
770 enum nb_client client
, const void *user
,
771 bool save_transaction
, const char *comment
,
772 uint32_t *transaction_id
);
775 * Lock the running configuration.
781 * Northbound user (can be NULL).
784 * 0 on success, -1 when the running configuration is already locked.
786 extern int nb_running_lock(enum nb_client client
, const void *user
);
789 * Unlock the running configuration.
795 * Northbound user (can be NULL).
798 * 0 on success, -1 when the running configuration is already unlocked or
799 * locked by another client/user.
801 extern int nb_running_unlock(enum nb_client client
, const void *user
);
804 * Check if the running configuration is locked or not for the given
811 * Northbound user (can be NULL).
814 * 0 if the running configuration is unlocked or if the client/user owns the
815 * lock, -1 otherwise.
817 extern int nb_running_lock_check(enum nb_client client
, const void *user
);
820 * Iterate over operational data.
823 * Data path of the YANG data we want to iterate over.
826 * YANG module translator (might be NULL).
829 * NB_OPER_DATA_ITER_ flags to control how the iteration is performed.
832 * Function to call with each data node.
835 * Arbitrary argument passed as the fourth parameter in each call to 'cb'.
838 * NB_OK on success, NB_ERR otherwise.
840 extern int nb_oper_data_iterate(const char *xpath
,
841 struct yang_translator
*translator
,
842 uint32_t flags
, nb_oper_data_cb cb
, void *arg
);
845 * Validate if the northbound operation is valid for the given node.
848 * Operation we want to check.
851 * libyang schema node we want to check.
854 * true if the operation is valid, false otherwise.
856 extern bool nb_operation_is_valid(enum nb_operation operation
,
857 const struct lys_node
*snode
);
860 * Send a YANG notification. This is a no-op unless the 'nb_notification_send'
861 * hook was registered by a northbound plugin.
864 * XPath of the YANG notification.
867 * Linked list containing the arguments that should be sent. This list is
868 * deleted after being used.
871 * NB_OK on success, NB_ERR otherwise.
873 extern int nb_notification_send(const char *xpath
, struct list
*arguments
);
876 * Associate a user pointer to a configuration node.
878 * This should be called by northbound 'create' callbacks in the NB_EV_APPLY
882 * libyang data node - only its XPath is used.
885 * Arbitrary user-specified pointer.
887 extern void nb_running_set_entry(const struct lyd_node
*dnode
, void *entry
);
890 * Unset the user pointer associated to a configuration node.
892 * This should be called by northbound 'destroy' callbacks in the NB_EV_APPLY
896 * libyang data node - only its XPath is used.
899 * The user pointer that was unset.
901 extern void *nb_running_unset_entry(const struct lyd_node
*dnode
);
904 * Find the user pointer (if any) associated to a configuration node.
906 * The XPath associated to the configuration node can be provided directly or
907 * indirectly through a libyang data node.
909 * If an user point is not found, this function follows the parent nodes in the
910 * running configuration until an user pointer is found or until the root node
914 * libyang data node - only its XPath is used (can be NULL if 'xpath' is
918 * XPath of the configuration node (can be NULL if 'dnode' is provided).
921 * When set to true, abort the program if no user pointer is found.
923 * As a rule of thumb, this parameter should be set to true in the following
925 * - Calling this function from any northbound configuration callback during
926 * the NB_EV_APPLY phase.
927 * - Calling this function from a 'delete' northbound configuration callback
930 * In both the above cases, the given configuration node should contain an
931 * user pointer except when there's a bug in the code, in which case it's
932 * better to abort the program right away and eliminate the need for
933 * unnecessary NULL checks.
935 * In all other cases, this parameter should be set to false and the caller
936 * should check if the function returned NULL or not.
939 * User pointer if found, NULL otherwise.
941 extern void *nb_running_get_entry(const struct lyd_node
*dnode
, const char *xpath
,
942 bool abort_if_not_found
);
945 * Return a human-readable string representing a northbound event.
951 * String representation of the given northbound event.
953 extern const char *nb_event_name(enum nb_event event
);
956 * Return a human-readable string representing a northbound operation.
959 * Northbound operation.
962 * String representation of the given northbound operation.
964 extern const char *nb_operation_name(enum nb_operation operation
);
967 * Return a human-readable string representing a northbound error.
973 * String representation of the given northbound error.
975 extern const char *nb_err_name(enum nb_error error
);
978 * Return a human-readable string representing a northbound client.
984 * String representation of the given northbound client.
986 extern const char *nb_client_name(enum nb_client client
);
989 * Initialize the northbound layer. Should be called only once during the
990 * daemon initialization process.
993 * Array of YANG modules to parse and initialize.
996 * Size of the modules array.
998 extern void nb_init(struct thread_master
*tm
, const struct frr_yang_module_info
*modules
[],
1002 * Finish the northbound layer gracefully. Should be called only when the daemon
1005 extern void nb_terminate(void);
1011 #endif /* _FRR_NORTHBOUND_H_ */