]> git.proxmox.com Git - mirror_frr.git/blob - lib/northbound.h
8ab6662ecc4908141717a4a9b9183eb640140fac
[mirror_frr.git] / lib / northbound.h
1 /*
2 * Copyright (C) 2018 NetDEF, Inc.
3 * Renato Westphal
4 *
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)
8 * any later version.
9 *
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
13 * more details.
14 *
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
18 */
19
20 #ifndef _FRR_NORTHBOUND_H_
21 #define _FRR_NORTHBOUND_H_
22
23 #include "hook.h"
24 #include "yang.h"
25 #include "linklist.h"
26 #include "openbsd-tree.h"
27
28 /* Forward declaration(s). */
29 struct vty;
30
31 /* Northbound events. */
32 enum nb_event {
33 /*
34 * The configuration callback is supposed to verify that the changes are
35 * valid and can be applied.
36 */
37 NB_EV_VALIDATE,
38
39 /*
40 * The configuration callback is supposed to prepare all resources
41 * required to apply the changes.
42 */
43 NB_EV_PREPARE,
44
45 /*
46 * Transaction has failed, the configuration callback needs to release
47 * all resources previously allocated.
48 */
49 NB_EV_ABORT,
50
51 /*
52 * The configuration changes need to be applied. The changes can't be
53 * rejected at this point (errors are logged and ignored).
54 */
55 NB_EV_APPLY,
56 };
57
58 /*
59 * Northbound operations.
60 *
61 * Refer to the documentation comments of nb_callbacks for more details.
62 */
63 enum nb_operation {
64 NB_OP_CREATE,
65 NB_OP_MODIFY,
66 NB_OP_DELETE,
67 NB_OP_MOVE,
68 NB_OP_APPLY_FINISH,
69 NB_OP_GET_ELEM,
70 NB_OP_GET_NEXT,
71 NB_OP_GET_KEYS,
72 NB_OP_LOOKUP_ENTRY,
73 NB_OP_RPC,
74 };
75
76 union nb_resource {
77 int fd;
78 void *ptr;
79 };
80
81 struct nb_callbacks {
82 /*
83 * Configuration callback.
84 *
85 * A presence container, list entry, leaf-list entry or leaf of type
86 * empty has been created.
87 *
88 * For presence-containers and list entries, the callback is supposed to
89 * initialize the default values of its children (if any) from the YANG
90 * models.
91 *
92 * event
93 * The transaction phase. Refer to the documentation comments of
94 * nb_event for more details.
95 *
96 * dnode
97 * libyang data node that is being created.
98 *
99 * resource
100 * Pointer to store resource(s) allocated during the NB_EV_PREPARE
101 * phase. The same pointer can be used during the NB_EV_ABORT and
102 * NB_EV_APPLY phases to either release or make use of the allocated
103 * resource(s). It's set to NULL when the event is NB_EV_VALIDATE.
104 *
105 * Returns:
106 * - NB_OK on success.
107 * - NB_ERR_VALIDATION when a validation error occurred.
108 * - NB_ERR_RESOURCE when the callback failed to allocate a resource.
109 * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
110 * - NB_ERR for other errors.
111 */
112 int (*create)(enum nb_event event, const struct lyd_node *dnode,
113 union nb_resource *resource);
114
115 /*
116 * Configuration callback.
117 *
118 * The value of a leaf has been modified.
119 *
120 * List keys don't need to implement this callback. When a list key is
121 * modified, the northbound treats this as if the list was deleted and a
122 * new one created with the updated key value.
123 *
124 * event
125 * The transaction phase. Refer to the documentation comments of
126 * nb_event for more details.
127 *
128 * dnode
129 * libyang data node that is being modified
130 *
131 * resource
132 * Pointer to store resource(s) allocated during the NB_EV_PREPARE
133 * phase. The same pointer can be used during the NB_EV_ABORT and
134 * NB_EV_APPLY phases to either release or make use of the allocated
135 * resource(s). It's set to NULL when the event is NB_EV_VALIDATE.
136 *
137 * Returns:
138 * - NB_OK on success.
139 * - NB_ERR_VALIDATION when a validation error occurred.
140 * - NB_ERR_RESOURCE when the callback failed to allocate a resource.
141 * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
142 * - NB_ERR for other errors.
143 */
144 int (*modify)(enum nb_event event, const struct lyd_node *dnode,
145 union nb_resource *resource);
146
147 /*
148 * Configuration callback.
149 *
150 * A presence container, list entry, leaf-list entry or optional leaf
151 * has been deleted.
152 *
153 * The callback is supposed to delete the entire configuration object,
154 * including its children when they exist.
155 *
156 * event
157 * The transaction phase. Refer to the documentation comments of
158 * nb_event for more details.
159 *
160 * dnode
161 * libyang data node that is being deleted.
162 *
163 * Returns:
164 * - NB_OK on success.
165 * - NB_ERR_VALIDATION when a validation error occurred.
166 * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
167 * - NB_ERR for other errors.
168 */
169 int (*delete)(enum nb_event event, const struct lyd_node *dnode);
170
171 /*
172 * Configuration callback.
173 *
174 * A list entry or leaf-list entry has been moved. Only applicable when
175 * the "ordered-by user" statement is present.
176 *
177 * event
178 * The transaction phase. Refer to the documentation comments of
179 * nb_event for more details.
180 *
181 * dnode
182 * libyang data node that is being moved.
183 *
184 * Returns:
185 * - NB_OK on success.
186 * - NB_ERR_VALIDATION when a validation error occurred.
187 * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
188 * - NB_ERR for other errors.
189 */
190 int (*move)(enum nb_event event, const struct lyd_node *dnode);
191
192 /*
193 * Optional configuration callback.
194 *
195 * The 'apply_finish' callbacks are called after all other callbacks
196 * during the apply phase (NB_EV_APPLY). These callbacks are called only
197 * under one of the following two cases:
198 * - The data node has been created or modified (but not deleted);
199 * - Any change was made within the descendants of the data node (e.g. a
200 * child leaf was modified, created or deleted).
201 *
202 * In the second case above, the 'apply_finish' callback is called only
203 * once even if multiple changes occurred within the descendants of the
204 * data node.
205 *
206 * dnode
207 * libyang data node associated with the 'apply_finish' callback.
208 */
209 void (*apply_finish)(const struct lyd_node *dnode);
210
211 /*
212 * Operational data callback.
213 *
214 * The callback function should return the value of a specific leaf or
215 * inform if a typeless value (presence containers or leafs of type
216 * empty) exists or not.
217 *
218 * xpath
219 * YANG data path of the data we want to get.
220 *
221 * list_entry
222 * Pointer to list entry.
223 *
224 * Returns:
225 * Pointer to newly created yang_data structure, or NULL to indicate
226 * the absence of data.
227 */
228 struct yang_data *(*get_elem)(const char *xpath,
229 const void *list_entry);
230
231 /*
232 * Operational data callback for YANG lists.
233 *
234 * The callback function should return the next entry in the list. The
235 * 'list_entry' parameter will be NULL on the first invocation.
236 *
237 * xpath
238 * Data path of the YANG list.
239 *
240 * list_entry
241 * Pointer to list entry.
242 *
243 * Returns:
244 * Pointer to the next entry in the list, or NULL to signal that the
245 * end of the list was reached.
246 */
247 const void *(*get_next)(const char *xpath, const void *list_entry);
248
249 /*
250 * Operational data callback for YANG lists.
251 *
252 * The callback function should fill the 'keys' parameter based on the
253 * given list_entry.
254 *
255 * list_entry
256 * Pointer to list entry.
257 *
258 * keys
259 * Structure to be filled based on the attributes of the provided
260 * list entry.
261 *
262 * Returns:
263 * NB_OK on success, NB_ERR otherwise.
264 */
265 int (*get_keys)(const void *list_entry, struct yang_list_keys *keys);
266
267 /*
268 * Operational data callback for YANG lists.
269 *
270 * The callback function should return a list entry based on the list
271 * keys given as a parameter.
272 *
273 * keys
274 * Structure containing the keys of the list entry.
275 *
276 * Returns:
277 * Pointer to the list entry if found, or NULL if not found.
278 */
279 const void *(*lookup_entry)(const struct yang_list_keys *keys);
280
281 /*
282 * RPC and action callback.
283 *
284 * Both 'input' and 'output' are lists of 'yang_data' structures. The
285 * callback should fetch all the input parameters from the 'input' list,
286 * and add output parameters to the 'output' list if necessary.
287 *
288 * xpath
289 * XPath of the YANG RPC or action.
290 *
291 * input
292 * Read-only list of input parameters.
293 *
294 * output
295 * List of output parameters to be populated by the callback.
296 *
297 * Returns:
298 * NB_OK on success, NB_ERR otherwise.
299 */
300 int (*rpc)(const char *xpath, const struct list *input,
301 struct list *output);
302
303 /*
304 * Optional callback to show the CLI command associated to the given
305 * YANG data node.
306 *
307 * vty
308 * The vty terminal to dump the configuration to.
309 *
310 * dnode
311 * libyang data node that should be shown in the form of a CLI
312 * command.
313 *
314 * show_defaults
315 * Specify whether to display default configuration values or not.
316 * This parameter can be ignored most of the time since the
317 * northbound doesn't call this callback for default leaves or
318 * non-presence containers that contain only default child nodes.
319 * The exception are commands associated to multiple configuration
320 * nodes, in which case it might be desirable to hide one or more
321 * parts of the command when this parameter is set to false.
322 */
323 void (*cli_show)(struct vty *vty, struct lyd_node *dnode,
324 bool show_defaults);
325 };
326
327 /*
328 * Northbound-specific data that is allocated for each schema node of the native
329 * YANG modules.
330 */
331 struct nb_node {
332 /* Back pointer to the libyang schema node. */
333 const struct lys_node *snode;
334
335 /* Data path of this YANG node. */
336 char xpath[XPATH_MAXLEN];
337
338 /* Priority - lower priorities are processed first. */
339 uint32_t priority;
340
341 /* Callbacks implemented for this node. */
342 struct nb_callbacks cbs;
343
344 /*
345 * Pointer to the parent node (disconsidering non-presence containers).
346 */
347 struct nb_node *parent;
348
349 /* Pointer to the nearest parent list, if any. */
350 struct nb_node *parent_list;
351
352 #ifdef HAVE_CONFD
353 /* ConfD hash value corresponding to this YANG path. */
354 int confd_hash;
355 #endif
356 };
357
358 struct frr_yang_module_info {
359 /* YANG module name. */
360 const char *name;
361
362 /* Northbound callbacks. */
363 const struct {
364 /* Data path of this YANG node. */
365 const char *xpath;
366
367 /* Callbacks implemented for this node. */
368 struct nb_callbacks cbs;
369
370 /* Priority - lower priorities are processed first. */
371 uint32_t priority;
372 } nodes[];
373 };
374
375 /* Northbound error codes. */
376 enum nb_error {
377 NB_OK = 0,
378 NB_ERR,
379 NB_ERR_NO_CHANGES,
380 NB_ERR_NOT_FOUND,
381 NB_ERR_LOCKED,
382 NB_ERR_VALIDATION,
383 NB_ERR_RESOURCE,
384 NB_ERR_INCONSISTENCY,
385 };
386
387 /* Default priority. */
388 #define NB_DFLT_PRIORITY (UINT32_MAX / 2)
389
390 /* Default maximum of configuration rollbacks to store. */
391 #define NB_DLFT_MAX_CONFIG_ROLLBACKS 20
392
393 /* Northbound clients. */
394 enum nb_client {
395 NB_CLIENT_CLI = 0,
396 NB_CLIENT_CONFD,
397 NB_CLIENT_SYSREPO,
398 };
399
400 /* Northbound configuration. */
401 struct nb_config {
402 struct lyd_node *dnode;
403 uint32_t version;
404 };
405
406 /* Northbound configuration callback. */
407 struct nb_config_cb {
408 RB_ENTRY(nb_config_cb) entry;
409 enum nb_operation operation;
410 char xpath[XPATH_MAXLEN];
411 const struct nb_node *nb_node;
412 const struct lyd_node *dnode;
413 };
414 RB_HEAD(nb_config_cbs, nb_config_cb);
415 RB_PROTOTYPE(nb_config_cbs, nb_config_cb, entry, nb_config_cb_compare);
416
417 /* Northbound configuration change. */
418 struct nb_config_change {
419 struct nb_config_cb cb;
420 union nb_resource resource;
421 bool prepare_ok;
422 };
423
424 /* Northbound configuration transaction. */
425 struct nb_transaction {
426 enum nb_client client;
427 char comment[80];
428 struct nb_config *config;
429 struct nb_config_cbs changes;
430 };
431
432 DECLARE_HOOK(nb_notification_send, (const char *xpath, struct list *arguments),
433 (xpath, arguments))
434
435 extern int debug_northbound;
436 extern struct nb_config *running_config;
437
438 /*
439 * Find the northbound node corresponding to a YANG data path.
440 *
441 * xpath
442 * XPath to search for (with or without predicates).
443 *
444 * Returns:
445 * Pointer to northbound node if found, NULL otherwise.
446 */
447 extern struct nb_node *nb_node_find(const char *xpath);
448
449 /*
450 * Create a new northbound configuration.
451 *
452 * dnode
453 * Pointer to a libyang data node containing the configuration data. If NULL
454 * is given, an empty configuration will be created.
455 *
456 * Returns:
457 * Pointer to newly created northbound configuration.
458 */
459 extern struct nb_config *nb_config_new(struct lyd_node *dnode);
460
461 /*
462 * Delete a northbound configuration.
463 *
464 * config
465 * Pointer to the config that is going to be deleted.
466 */
467 extern void nb_config_free(struct nb_config *config);
468
469 /*
470 * Duplicate a northbound configuration.
471 *
472 * config
473 * Northbound configuration to duplicate.
474 *
475 * Returns:
476 * Pointer to duplicated configuration.
477 */
478 extern struct nb_config *nb_config_dup(const struct nb_config *config);
479
480 /*
481 * Merge one configuration into another.
482 *
483 * config_dst
484 * Configuration to merge to.
485 *
486 * config_src
487 * Configuration to merge config_dst with.
488 *
489 * preserve_source
490 * Specify whether config_src should be deleted or not after the merge
491 * operation.
492 *
493 * Returns:
494 * NB_OK on success, NB_ERR otherwise.
495 */
496 extern int nb_config_merge(struct nb_config *config_dst,
497 struct nb_config *config_src, bool preserve_source);
498
499 /*
500 * Replace one configuration by another.
501 *
502 * config_dst
503 * Configuration to be replaced.
504 *
505 * config_src
506 * Configuration to replace config_dst.
507 *
508 * preserve_source
509 * Specify whether config_src should be deleted or not after the replace
510 * operation.
511 */
512 extern void nb_config_replace(struct nb_config *config_dst,
513 struct nb_config *config_src,
514 bool preserve_source);
515
516 /*
517 * Edit a candidate configuration.
518 *
519 * candidate
520 * Candidate configuration to edit.
521 *
522 * nb_node
523 * Northbound node associated to the configuration being edited.
524 *
525 * operation
526 * Operation to apply.
527 *
528 * xpath
529 * XPath of the configuration node being edited.
530 *
531 * previous
532 * Previous value of the configuration node. Should be used only when the
533 * operation is NB_OP_MOVE, otherwise this parameter is ignored.
534 *
535 * data
536 * New value of the configuration node.
537 *
538 * Returns:
539 * - NB_OK on success.
540 * - NB_ERR_NOT_FOUND when the element to be deleted was not found.
541 * - NB_ERR for other errors.
542 */
543 extern int nb_candidate_edit(struct nb_config *candidate,
544 const struct nb_node *nb_node,
545 enum nb_operation operation, const char *xpath,
546 const struct yang_data *previous,
547 const struct yang_data *data);
548
549 /*
550 * Check if a candidate configuration is outdated and needs to be updated.
551 *
552 * candidate
553 * Candidate configuration to check.
554 *
555 * Returns:
556 * true if the candidate is outdated, false otherwise.
557 */
558 extern bool nb_candidate_needs_update(const struct nb_config *candidate);
559
560 /*
561 * Update a candidate configuration by rebasing the changes on top of the latest
562 * running configuration. Resolve conflicts automatically by giving preference
563 * to the changes done in the candidate configuration.
564 *
565 * candidate
566 * Candidate configuration to update.
567 *
568 * Returns:
569 * NB_OK on success, NB_ERR otherwise.
570 */
571 extern int nb_candidate_update(struct nb_config *candidate);
572
573 /*
574 * Validate a candidate configuration. Perform both YANG syntactic/semantic
575 * validation and code-level validation using the northbound callbacks.
576 *
577 * WARNING: the candidate can be modified as part of the validation process
578 * (e.g. add default nodes).
579 *
580 * candidate
581 * Candidate configuration to validate.
582 *
583 * Returns:
584 * NB_OK on success, NB_ERR_VALIDATION otherwise.
585 */
586 extern int nb_candidate_validate(struct nb_config *candidate);
587
588 /*
589 * Create a new configuration transaction but do not commit it yet. Only
590 * validate the candidate and prepare all resources required to apply the
591 * configuration changes.
592 *
593 * candidate
594 * Candidate configuration to commit.
595 *
596 * client
597 * Northbound client performing the commit.
598 *
599 * comment
600 * Optional comment describing the commit.
601 *
602 * transaction
603 * Output parameter providing the created transaction when one is created
604 * successfully. In this case, it must be either aborted using
605 * nb_candidate_commit_abort() or committed using
606 * nb_candidate_commit_apply().
607 *
608 * Returns:
609 * - NB_OK on success.
610 * - NB_ERR_NO_CHANGES when the candidate is identical to the running
611 * configuration.
612 * - NB_ERR_LOCKED when there's already another transaction in progress.
613 * - NB_ERR_VALIDATION when the candidate fails the validation checks.
614 * - NB_ERR_RESOURCE when the system fails to allocate resources to apply
615 * the candidate configuration.
616 * - NB_ERR for other errors.
617 */
618 extern int nb_candidate_commit_prepare(struct nb_config *candidate,
619 enum nb_client client,
620 const char *comment,
621 struct nb_transaction **transaction);
622
623 /*
624 * Abort a previously created configuration transaction, releasing all resources
625 * allocated during the preparation phase.
626 *
627 * transaction
628 * Candidate configuration to abort. It's consumed by this function.
629 */
630 extern void nb_candidate_commit_abort(struct nb_transaction *transaction);
631
632 /*
633 * Commit a previously created configuration transaction.
634 *
635 * transaction
636 * Configuration transaction to commit. It's consumed by this function.
637 *
638 * save_transaction
639 * Specify whether the transaction should be recorded in the transactions log
640 * or not.
641 *
642 * transaction_id
643 * Optional output parameter providing the ID of the committed transaction.
644 */
645 extern void nb_candidate_commit_apply(struct nb_transaction *transaction,
646 bool save_transaction,
647 uint32_t *transaction_id);
648
649 /*
650 * Create a new transaction to commit a candidate configuration. This is a
651 * convenience function that performs the two-phase commit protocol
652 * transparently to the user. The cost is reduced flexibility, since
653 * network-wide and multi-daemon transactions require the network manager to
654 * take into account the results of the preparation phase of multiple managed
655 * entities.
656 *
657 * candidate
658 * Candidate configuration to commit. It's preserved regardless if the commit
659 * operation fails or not.
660 *
661 * client
662 * Northbound client performing the commit.
663 *
664 * save_transaction
665 * Specify whether the transaction should be recorded in the transactions log
666 * or not.
667 *
668 * comment
669 * Optional comment describing the commit.
670 *
671 * transaction_id
672 * Optional output parameter providing the ID of the committed transaction.
673 *
674 * Returns:
675 * - NB_OK on success.
676 * - NB_ERR_NO_CHANGES when the candidate is identical to the running
677 * configuration.
678 * - NB_ERR_LOCKED when there's already another transaction in progress.
679 * - NB_ERR_VALIDATION when the candidate fails the validation checks.
680 * - NB_ERR_RESOURCE when the system fails to allocate resources to apply
681 * the candidate configuration.
682 * - NB_ERR for other errors.
683 */
684 extern int nb_candidate_commit(struct nb_config *candidate,
685 enum nb_client client, bool save_transaction,
686 const char *comment, uint32_t *transaction_id);
687
688 /*
689 * Validate if the northbound operation is valid for the given node.
690 *
691 * operation
692 * Operation we want to check.
693 *
694 * snode
695 * libyang schema node we want to check.
696 *
697 * Returns:
698 * true if the operation is valid, false otherwise.
699 */
700 extern bool nb_operation_is_valid(enum nb_operation operation,
701 const struct lys_node *snode);
702
703 /*
704 * Send a YANG notification. This is a no-op unless the 'nb_notification_send'
705 * hook was registered by a northbound plugin.
706 *
707 * xpath
708 * XPath of the YANG notification.
709 *
710 * arguments
711 * Linked list containing the arguments that should be sent. This list is
712 * deleted after being used.
713 *
714 * Returns:
715 * NB_OK on success, NB_ERR otherwise.
716 */
717 extern int nb_notification_send(const char *xpath, struct list *arguments);
718
719 /*
720 * Return a human-readable string representing a northbound event.
721 *
722 * event
723 * Northbound event.
724 *
725 * Returns:
726 * String representation of the given northbound event.
727 */
728 extern const char *nb_event_name(enum nb_event event);
729
730 /*
731 * Return a human-readable string representing a northbound operation.
732 *
733 * operation
734 * Northbound operation.
735 *
736 * Returns:
737 * String representation of the given northbound operation.
738 */
739 extern const char *nb_operation_name(enum nb_operation operation);
740
741 /*
742 * Return a human-readable string representing a northbound error.
743 *
744 * error
745 * Northbound error.
746 *
747 * Returns:
748 * String representation of the given northbound error.
749 */
750 extern const char *nb_err_name(enum nb_error error);
751
752 /*
753 * Return a human-readable string representing a northbound client.
754 *
755 * client
756 * Northbound client.
757 *
758 * Returns:
759 * String representation of the given northbound client.
760 */
761 extern const char *nb_client_name(enum nb_client client);
762
763 /*
764 * Initialize the northbound layer. Should be called only once during the
765 * daemon initialization process.
766 *
767 * modules
768 * Array of YANG modules to parse and initialize.
769 *
770 * nmodules
771 * Size of the modules array.
772 */
773 extern void nb_init(const struct frr_yang_module_info *modules[],
774 size_t nmodules);
775
776 /*
777 * Finish the northbound layer gracefully. Should be called only when the daemon
778 * is exiting.
779 */
780 extern void nb_terminate(void);
781
782 #endif /* _FRR_NORTHBOUND_H_ */