Line data Source code
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 "thread.h"
24 : #include "hook.h"
25 : #include "linklist.h"
26 : #include "openbsd-tree.h"
27 : #include "yang.h"
28 : #include "yang_translator.h"
29 :
30 : #ifdef __cplusplus
31 : extern "C" {
32 : #endif
33 :
34 : /* Forward declaration(s). */
35 : struct vty;
36 : struct debug;
37 :
38 : /* Northbound events. */
39 : enum nb_event {
40 : /*
41 : * The configuration callback is supposed to verify that the changes are
42 : * valid and can be applied.
43 : */
44 : NB_EV_VALIDATE,
45 :
46 : /*
47 : * The configuration callback is supposed to prepare all resources
48 : * required to apply the changes.
49 : */
50 : NB_EV_PREPARE,
51 :
52 : /*
53 : * Transaction has failed, the configuration callback needs to release
54 : * all resources previously allocated.
55 : */
56 : NB_EV_ABORT,
57 :
58 : /*
59 : * The configuration changes need to be applied. The changes can't be
60 : * rejected at this point (errors are logged and ignored).
61 : */
62 : NB_EV_APPLY,
63 : };
64 :
65 : /*
66 : * Northbound operations.
67 : *
68 : * Refer to the documentation comments of nb_callbacks for more details.
69 : */
70 : enum nb_operation {
71 : NB_OP_CREATE,
72 : NB_OP_MODIFY,
73 : NB_OP_DESTROY,
74 : NB_OP_MOVE,
75 : NB_OP_PRE_VALIDATE,
76 : NB_OP_APPLY_FINISH,
77 : NB_OP_GET_ELEM,
78 : NB_OP_GET_NEXT,
79 : NB_OP_GET_KEYS,
80 : NB_OP_LOOKUP_ENTRY,
81 : NB_OP_RPC,
82 : };
83 :
84 : union nb_resource {
85 : int fd;
86 : void *ptr;
87 : };
88 :
89 : /*
90 : * Northbound callbacks parameters.
91 : */
92 :
93 : struct nb_cb_create_args {
94 : /* Context of the configuration transaction. */
95 : struct nb_context *context;
96 :
97 : /*
98 : * The transaction phase. Refer to the documentation comments of
99 : * nb_event for more details.
100 : */
101 : enum nb_event event;
102 :
103 : /* libyang data node that is being created. */
104 : const struct lyd_node *dnode;
105 :
106 : /*
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.
111 : */
112 : union nb_resource *resource;
113 :
114 : /* Buffer to store human-readable error message in case of error. */
115 : char *errmsg;
116 :
117 : /* Size of errmsg. */
118 : size_t errmsg_len;
119 : };
120 :
121 : struct nb_cb_modify_args {
122 : /* Context of the configuration transaction. */
123 : struct nb_context *context;
124 :
125 : /*
126 : * The transaction phase. Refer to the documentation comments of
127 : * nb_event for more details.
128 : */
129 : enum nb_event event;
130 :
131 : /* libyang data node that is being modified. */
132 : const struct lyd_node *dnode;
133 :
134 : /*
135 : * Pointer to store resource(s) allocated during the NB_EV_PREPARE
136 : * phase. The same pointer can be used during the NB_EV_ABORT and
137 : * NB_EV_APPLY phases to either release or make use of the allocated
138 : * resource(s). It's set to NULL when the event is NB_EV_VALIDATE.
139 : */
140 : union nb_resource *resource;
141 :
142 : /* Buffer to store human-readable error message in case of error. */
143 : char *errmsg;
144 :
145 : /* Size of errmsg. */
146 : size_t errmsg_len;
147 : };
148 :
149 : struct nb_cb_destroy_args {
150 : /* Context of the configuration transaction. */
151 : struct nb_context *context;
152 :
153 : /*
154 : * The transaction phase. Refer to the documentation comments of
155 : * nb_event for more details.
156 : */
157 : enum nb_event event;
158 :
159 : /* libyang data node that is being deleted. */
160 : const struct lyd_node *dnode;
161 :
162 : /* Buffer to store human-readable error message in case of error. */
163 : char *errmsg;
164 :
165 : /* Size of errmsg. */
166 : size_t errmsg_len;
167 : };
168 :
169 : struct nb_cb_move_args {
170 : /* Context of the configuration transaction. */
171 : struct nb_context *context;
172 :
173 : /*
174 : * The transaction phase. Refer to the documentation comments of
175 : * nb_event for more details.
176 : */
177 : enum nb_event event;
178 :
179 : /* libyang data node that is being moved. */
180 : const struct lyd_node *dnode;
181 :
182 : /* Buffer to store human-readable error message in case of error. */
183 : char *errmsg;
184 :
185 : /* Size of errmsg. */
186 : size_t errmsg_len;
187 : };
188 :
189 : struct nb_cb_pre_validate_args {
190 : /* Context of the configuration transaction. */
191 : struct nb_context *context;
192 :
193 : /* libyang data node associated with the 'pre_validate' callback. */
194 : const struct lyd_node *dnode;
195 :
196 : /* Buffer to store human-readable error message in case of error. */
197 : char *errmsg;
198 :
199 : /* Size of errmsg. */
200 : size_t errmsg_len;
201 : };
202 :
203 : struct nb_cb_apply_finish_args {
204 : /* Context of the configuration transaction. */
205 : struct nb_context *context;
206 :
207 : /* libyang data node associated with the 'apply_finish' callback. */
208 : const struct lyd_node *dnode;
209 :
210 : /* Buffer to store human-readable error message in case of error. */
211 : char *errmsg;
212 :
213 : /* Size of errmsg. */
214 : size_t errmsg_len;
215 : };
216 :
217 : struct nb_cb_get_elem_args {
218 : /* YANG data path of the data we want to get. */
219 : const char *xpath;
220 :
221 : /* Pointer to list entry (might be NULL). */
222 : const void *list_entry;
223 : };
224 :
225 : struct nb_cb_get_next_args {
226 : /* Pointer to parent list entry. */
227 : const void *parent_list_entry;
228 :
229 : /* Pointer to (leaf-)list entry. */
230 : const void *list_entry;
231 : };
232 :
233 : struct nb_cb_get_keys_args {
234 : /* Pointer to list entry. */
235 : const void *list_entry;
236 :
237 : /*
238 : * Structure to be filled based on the attributes of the provided list
239 : * entry.
240 : */
241 : struct yang_list_keys *keys;
242 : };
243 :
244 : struct nb_cb_lookup_entry_args {
245 : /* Pointer to parent list entry. */
246 : const void *parent_list_entry;
247 :
248 : /* Structure containing the keys of the list entry. */
249 : const struct yang_list_keys *keys;
250 : };
251 :
252 : struct nb_cb_rpc_args {
253 : /* XPath of the YANG RPC or action. */
254 : const char *xpath;
255 :
256 : /* Read-only list of input parameters. */
257 : const struct list *input;
258 :
259 : /* List of output parameters to be populated by the callback. */
260 : struct list *output;
261 :
262 : /* Buffer to store human-readable error message in case of error. */
263 : char *errmsg;
264 :
265 : /* Size of errmsg. */
266 : size_t errmsg_len;
267 : };
268 :
269 : /*
270 : * Set of configuration callbacks that can be associated to a northbound node.
271 : */
272 : struct nb_callbacks {
273 : /*
274 : * Configuration callback.
275 : *
276 : * A presence container, list entry, leaf-list entry or leaf of type
277 : * empty has been created.
278 : *
279 : * For presence-containers and list entries, the callback is supposed to
280 : * initialize the default values of its children (if any) from the YANG
281 : * models.
282 : *
283 : * args
284 : * Refer to the documentation comments of nb_cb_create_args for
285 : * details.
286 : *
287 : * Returns:
288 : * - NB_OK on success.
289 : * - NB_ERR_VALIDATION when a validation error occurred.
290 : * - NB_ERR_RESOURCE when the callback failed to allocate a resource.
291 : * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
292 : * - NB_ERR for other errors.
293 : */
294 : int (*create)(struct nb_cb_create_args *args);
295 :
296 : /*
297 : * Configuration callback.
298 : *
299 : * The value of a leaf has been modified.
300 : *
301 : * List keys don't need to implement this callback. When a list key is
302 : * modified, the northbound treats this as if the list was deleted and a
303 : * new one created with the updated key value.
304 : *
305 : * args
306 : * Refer to the documentation comments of nb_cb_modify_args for
307 : * details.
308 : *
309 : * Returns:
310 : * - NB_OK on success.
311 : * - NB_ERR_VALIDATION when a validation error occurred.
312 : * - NB_ERR_RESOURCE when the callback failed to allocate a resource.
313 : * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
314 : * - NB_ERR for other errors.
315 : */
316 : int (*modify)(struct nb_cb_modify_args *args);
317 :
318 : /*
319 : * Configuration callback.
320 : *
321 : * A presence container, list entry, leaf-list entry or optional leaf
322 : * has been deleted.
323 : *
324 : * The callback is supposed to delete the entire configuration object,
325 : * including its children when they exist.
326 : *
327 : * args
328 : * Refer to the documentation comments of nb_cb_destroy_args for
329 : * details.
330 : *
331 : * Returns:
332 : * - NB_OK on success.
333 : * - NB_ERR_VALIDATION when a validation error occurred.
334 : * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
335 : * - NB_ERR for other errors.
336 : */
337 : int (*destroy)(struct nb_cb_destroy_args *args);
338 :
339 : /*
340 : * Configuration callback.
341 : *
342 : * A list entry or leaf-list entry has been moved. Only applicable when
343 : * the "ordered-by user" statement is present.
344 : *
345 : * args
346 : * Refer to the documentation comments of nb_cb_move_args for
347 : * details.
348 : *
349 : * Returns:
350 : * - NB_OK on success.
351 : * - NB_ERR_VALIDATION when a validation error occurred.
352 : * - NB_ERR_INCONSISTENCY when an inconsistency was detected.
353 : * - NB_ERR for other errors.
354 : */
355 : int (*move)(struct nb_cb_move_args *args);
356 :
357 : /*
358 : * Optional configuration callback.
359 : *
360 : * This callback can be used to validate subsections of the
361 : * configuration being committed before validating the configuration
362 : * changes themselves. It's useful to perform more complex validations
363 : * that depend on the relationship between multiple nodes.
364 : *
365 : * args
366 : * Refer to the documentation comments of nb_cb_pre_validate_args for
367 : * details.
368 : *
369 : * Returns:
370 : * - NB_OK on success.
371 : * - NB_ERR_VALIDATION when a validation error occurred.
372 : */
373 : int (*pre_validate)(struct nb_cb_pre_validate_args *args);
374 :
375 : /*
376 : * Optional configuration callback.
377 : *
378 : * The 'apply_finish' callbacks are called after all other callbacks
379 : * during the apply phase (NB_EV_APPLY). These callbacks are called only
380 : * under one of the following two cases:
381 : * - The data node has been created or modified (but not deleted);
382 : * - Any change was made within the descendants of the data node (e.g. a
383 : * child leaf was modified, created or deleted).
384 : *
385 : * In the second case above, the 'apply_finish' callback is called only
386 : * once even if multiple changes occurred within the descendants of the
387 : * data node.
388 : *
389 : * args
390 : * Refer to the documentation comments of nb_cb_apply_finish_args for
391 : * details.
392 : */
393 : void (*apply_finish)(struct nb_cb_apply_finish_args *args);
394 :
395 : /*
396 : * Operational data callback.
397 : *
398 : * The callback function should return the value of a specific leaf,
399 : * leaf-list entry or inform if a typeless value (presence containers or
400 : * leafs of type empty) exists or not.
401 : *
402 : * args
403 : * Refer to the documentation comments of nb_cb_get_elem_args for
404 : * details.
405 : *
406 : * Returns:
407 : * Pointer to newly created yang_data structure, or NULL to indicate
408 : * the absence of data.
409 : */
410 : struct yang_data *(*get_elem)(struct nb_cb_get_elem_args *args);
411 :
412 : /*
413 : * Operational data callback for YANG lists and leaf-lists.
414 : *
415 : * The callback function should return the next entry in the list or
416 : * leaf-list. The 'list_entry' parameter will be NULL on the first
417 : * invocation.
418 : *
419 : * args
420 : * Refer to the documentation comments of nb_cb_get_next_args for
421 : * details.
422 : *
423 : * Returns:
424 : * Pointer to the next entry in the (leaf-)list, or NULL to signal
425 : * that the end of the (leaf-)list was reached.
426 : */
427 : const void *(*get_next)(struct nb_cb_get_next_args *args);
428 :
429 : /*
430 : * Operational data callback for YANG lists.
431 : *
432 : * The callback function should fill the 'keys' parameter based on the
433 : * given list_entry. Keyless lists don't need to implement this
434 : * callback.
435 : *
436 : * args
437 : * Refer to the documentation comments of nb_cb_get_keys_args for
438 : * details.
439 : *
440 : * Returns:
441 : * NB_OK on success, NB_ERR otherwise.
442 : */
443 : int (*get_keys)(struct nb_cb_get_keys_args *args);
444 :
445 : /*
446 : * Operational data callback for YANG lists.
447 : *
448 : * The callback function should return a list entry based on the list
449 : * keys given as a parameter. Keyless lists don't need to implement this
450 : * callback.
451 : *
452 : * args
453 : * Refer to the documentation comments of nb_cb_lookup_entry_args for
454 : * details.
455 : *
456 : * Returns:
457 : * Pointer to the list entry if found, or NULL if not found.
458 : */
459 : const void *(*lookup_entry)(struct nb_cb_lookup_entry_args *args);
460 :
461 : /*
462 : * RPC and action callback.
463 : *
464 : * Both 'input' and 'output' are lists of 'yang_data' structures. The
465 : * callback should fetch all the input parameters from the 'input' list,
466 : * and add output parameters to the 'output' list if necessary.
467 : *
468 : * args
469 : * Refer to the documentation comments of nb_cb_rpc_args for details.
470 : *
471 : * Returns:
472 : * NB_OK on success, NB_ERR otherwise.
473 : */
474 : int (*rpc)(struct nb_cb_rpc_args *args);
475 :
476 : /*
477 : * Optional callback to compare the data nodes when printing
478 : * the CLI commands associated with them.
479 : *
480 : * dnode1
481 : * The first data node to compare.
482 : *
483 : * dnode2
484 : * The second data node to compare.
485 : *
486 : * Returns:
487 : * <0 when the CLI command for the dnode1 should be printed first
488 : * >0 when the CLI command for the dnode2 should be printed first
489 : * 0 when there is no difference
490 : */
491 : int (*cli_cmp)(const struct lyd_node *dnode1,
492 : const struct lyd_node *dnode2);
493 :
494 : /*
495 : * Optional callback to show the CLI command associated to the given
496 : * YANG data node.
497 : *
498 : * vty
499 : * The vty terminal to dump the configuration to.
500 : *
501 : * dnode
502 : * libyang data node that should be shown in the form of a CLI
503 : * command.
504 : *
505 : * show_defaults
506 : * Specify whether to display default configuration values or not.
507 : * This parameter can be ignored most of the time since the
508 : * northbound doesn't call this callback for default leaves or
509 : * non-presence containers that contain only default child nodes.
510 : * The exception are commands associated to multiple configuration
511 : * nodes, in which case it might be desirable to hide one or more
512 : * parts of the command when this parameter is set to false.
513 : */
514 : void (*cli_show)(struct vty *vty, const struct lyd_node *dnode,
515 : bool show_defaults);
516 :
517 : /*
518 : * Optional callback to show the CLI node end for lists or containers.
519 : *
520 : * vty
521 : * The vty terminal to dump the configuration to.
522 : *
523 : * dnode
524 : * libyang data node that should be shown in the form of a CLI
525 : * command.
526 : */
527 : void (*cli_show_end)(struct vty *vty, const struct lyd_node *dnode);
528 : };
529 :
530 : struct nb_dependency_callbacks {
531 : void (*get_dependant_xpath)(const struct lyd_node *dnode, char *xpath);
532 : void (*get_dependency_xpath)(const struct lyd_node *dnode, char *xpath);
533 : };
534 :
535 : /*
536 : * Northbound-specific data that is allocated for each schema node of the native
537 : * YANG modules.
538 : */
539 : struct nb_node {
540 : /* Back pointer to the libyang schema node. */
541 : const struct lysc_node *snode;
542 :
543 : /* Data path of this YANG node. */
544 : char xpath[XPATH_MAXLEN];
545 :
546 : /* Priority - lower priorities are processed first. */
547 : uint32_t priority;
548 :
549 : struct nb_dependency_callbacks dep_cbs;
550 :
551 : /* Callbacks implemented for this node. */
552 : struct nb_callbacks cbs;
553 :
554 : /*
555 : * Pointer to the parent node (disconsidering non-presence containers).
556 : */
557 : struct nb_node *parent;
558 :
559 : /* Pointer to the nearest parent list, if any. */
560 : struct nb_node *parent_list;
561 :
562 : /* Flags. */
563 : uint8_t flags;
564 :
565 : #ifdef HAVE_CONFD
566 : /* ConfD hash value corresponding to this YANG path. */
567 : int confd_hash;
568 : #endif
569 : };
570 : /* The YANG container or list contains only config data. */
571 : #define F_NB_NODE_CONFIG_ONLY 0x01
572 : /* The YANG list doesn't contain key leafs. */
573 : #define F_NB_NODE_KEYLESS_LIST 0x02
574 :
575 : /*
576 : * HACK: old gcc versions (< 5.x) have a bug that prevents C99 flexible arrays
577 : * from working properly on shared libraries. For those compilers, use a fixed
578 : * size array to work around the problem.
579 : */
580 : #define YANG_MODULE_MAX_NODES 2000
581 :
582 : struct frr_yang_module_info {
583 : /* YANG module name. */
584 : const char *name;
585 :
586 : /* Northbound callbacks. */
587 : const struct {
588 : /* Data path of this YANG node. */
589 : const char *xpath;
590 :
591 : /* Callbacks implemented for this node. */
592 : struct nb_callbacks cbs;
593 :
594 : /* Priority - lower priorities are processed first. */
595 : uint32_t priority;
596 : #if defined(__GNUC__) && ((__GNUC__ - 0) < 5) && !defined(__clang__)
597 : } nodes[YANG_MODULE_MAX_NODES + 1];
598 : #else
599 : } nodes[];
600 : #endif
601 : };
602 :
603 : /* Northbound error codes. */
604 : enum nb_error {
605 : NB_OK = 0,
606 : NB_ERR,
607 : NB_ERR_NO_CHANGES,
608 : NB_ERR_NOT_FOUND,
609 : NB_ERR_LOCKED,
610 : NB_ERR_VALIDATION,
611 : NB_ERR_RESOURCE,
612 : NB_ERR_INCONSISTENCY,
613 : };
614 :
615 : /* Default priority. */
616 : #define NB_DFLT_PRIORITY (UINT32_MAX / 2)
617 :
618 : /* Default maximum of configuration rollbacks to store. */
619 : #define NB_DLFT_MAX_CONFIG_ROLLBACKS 20
620 :
621 : /* Northbound clients. */
622 : enum nb_client {
623 : NB_CLIENT_NONE = 0,
624 : NB_CLIENT_CLI,
625 : NB_CLIENT_CONFD,
626 : NB_CLIENT_SYSREPO,
627 : NB_CLIENT_GRPC,
628 : NB_CLIENT_PCEP,
629 : };
630 :
631 : /* Northbound context. */
632 : struct nb_context {
633 : /* Northbound client. */
634 : enum nb_client client;
635 :
636 : /* Northbound user (can be NULL). */
637 : const void *user;
638 :
639 : /* Client-specific data. */
640 : #if 0
641 : union {
642 : struct {
643 : } cli;
644 : struct {
645 : } confd;
646 : struct {
647 : } sysrepo;
648 : struct {
649 : } grpc;
650 : struct {
651 : } pcep;
652 : } client_data;
653 : #endif
654 : };
655 :
656 : /* Northbound configuration. */
657 : struct nb_config {
658 : struct lyd_node *dnode;
659 : uint32_t version;
660 : };
661 :
662 : /* Northbound configuration callback. */
663 : struct nb_config_cb {
664 : RB_ENTRY(nb_config_cb) entry;
665 : enum nb_operation operation;
666 : uint32_t seq;
667 : const struct nb_node *nb_node;
668 : const struct lyd_node *dnode;
669 : };
670 : RB_HEAD(nb_config_cbs, nb_config_cb);
671 557 : RB_PROTOTYPE(nb_config_cbs, nb_config_cb, entry, nb_config_cb_compare);
672 :
673 : /* Northbound configuration change. */
674 : struct nb_config_change {
675 : struct nb_config_cb cb;
676 : union nb_resource resource;
677 : bool prepare_ok;
678 : };
679 :
680 : /* Northbound configuration transaction. */
681 : struct nb_transaction {
682 : struct nb_context *context;
683 : char comment[80];
684 : struct nb_config *config;
685 : struct nb_config_cbs changes;
686 : };
687 :
688 : /* Callback function used by nb_oper_data_iterate(). */
689 : typedef int (*nb_oper_data_cb)(const struct lysc_node *snode,
690 : struct yang_translator *translator,
691 : struct yang_data *data, void *arg);
692 :
693 : /* Iterate over direct child nodes only. */
694 : #define NB_OPER_DATA_ITER_NORECURSE 0x0001
695 :
696 : /* Hooks. */
697 : DECLARE_HOOK(nb_notification_send, (const char *xpath, struct list *arguments),
698 : (xpath, arguments));
699 : DECLARE_HOOK(nb_client_debug_config_write, (struct vty *vty), (vty));
700 : DECLARE_HOOK(nb_client_debug_set_all, (uint32_t flags, bool set), (flags, set));
701 :
702 : /* Northbound debugging records */
703 : extern struct debug nb_dbg_cbs_config;
704 : extern struct debug nb_dbg_cbs_state;
705 : extern struct debug nb_dbg_cbs_rpc;
706 : extern struct debug nb_dbg_notif;
707 : extern struct debug nb_dbg_events;
708 : extern struct debug nb_dbg_libyang;
709 :
710 : /* Global running configuration. */
711 : extern struct nb_config *running_config;
712 :
713 : /* Wrappers for the northbound callbacks. */
714 : extern struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node,
715 : const char *xpath,
716 : const void *list_entry);
717 : extern const void *nb_callback_get_next(const struct nb_node *nb_node,
718 : const void *parent_list_entry,
719 : const void *list_entry);
720 : extern int nb_callback_get_keys(const struct nb_node *nb_node,
721 : const void *list_entry,
722 : struct yang_list_keys *keys);
723 : extern const void *nb_callback_lookup_entry(const struct nb_node *nb_node,
724 : const void *parent_list_entry,
725 : const struct yang_list_keys *keys);
726 : extern int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
727 : const struct list *input, struct list *output,
728 : char *errmsg, size_t errmsg_len);
729 :
730 : /*
731 : * Create a northbound node for all YANG schema nodes.
732 : */
733 : void nb_nodes_create(void);
734 :
735 : /*
736 : * Delete all northbound nodes from all YANG schema nodes.
737 : */
738 : void nb_nodes_delete(void);
739 :
740 : /*
741 : * Find the northbound node corresponding to a YANG data path.
742 : *
743 : * xpath
744 : * XPath to search for (with or without predicates).
745 : *
746 : * Returns:
747 : * Pointer to northbound node if found, NULL otherwise.
748 : */
749 : extern struct nb_node *nb_node_find(const char *xpath);
750 :
751 : extern void nb_node_set_dependency_cbs(const char *dependency_xpath,
752 : const char *dependant_xpath,
753 : struct nb_dependency_callbacks *cbs);
754 :
755 : bool nb_node_has_dependency(struct nb_node *node);
756 :
757 : /*
758 : * Create a new northbound configuration.
759 : *
760 : * dnode
761 : * Pointer to a libyang data node containing the configuration data. If NULL
762 : * is given, an empty configuration will be created.
763 : *
764 : * Returns:
765 : * Pointer to newly created northbound configuration.
766 : */
767 : extern struct nb_config *nb_config_new(struct lyd_node *dnode);
768 :
769 : /*
770 : * Delete a northbound configuration.
771 : *
772 : * config
773 : * Pointer to the config that is going to be deleted.
774 : */
775 : extern void nb_config_free(struct nb_config *config);
776 :
777 : /*
778 : * Duplicate a northbound configuration.
779 : *
780 : * config
781 : * Northbound configuration to duplicate.
782 : *
783 : * Returns:
784 : * Pointer to duplicated configuration.
785 : */
786 : extern struct nb_config *nb_config_dup(const struct nb_config *config);
787 :
788 : /*
789 : * Merge one configuration into another.
790 : *
791 : * config_dst
792 : * Configuration to merge to.
793 : *
794 : * config_src
795 : * Configuration to merge config_dst with.
796 : *
797 : * preserve_source
798 : * Specify whether config_src should be deleted or not after the merge
799 : * operation.
800 : *
801 : * Returns:
802 : * NB_OK on success, NB_ERR otherwise.
803 : */
804 : extern int nb_config_merge(struct nb_config *config_dst,
805 : struct nb_config *config_src, bool preserve_source);
806 :
807 : /*
808 : * Replace one configuration by another.
809 : *
810 : * config_dst
811 : * Configuration to be replaced.
812 : *
813 : * config_src
814 : * Configuration to replace config_dst.
815 : *
816 : * preserve_source
817 : * Specify whether config_src should be deleted or not after the replace
818 : * operation.
819 : */
820 : extern void nb_config_replace(struct nb_config *config_dst,
821 : struct nb_config *config_src,
822 : bool preserve_source);
823 :
824 : /*
825 : * Edit a candidate configuration.
826 : *
827 : * candidate
828 : * Candidate configuration to edit.
829 : *
830 : * nb_node
831 : * Northbound node associated to the configuration being edited.
832 : *
833 : * operation
834 : * Operation to apply.
835 : *
836 : * xpath
837 : * XPath of the configuration node being edited.
838 : *
839 : * previous
840 : * Previous value of the configuration node. Should be used only when the
841 : * operation is NB_OP_MOVE, otherwise this parameter is ignored.
842 : *
843 : * data
844 : * New value of the configuration node.
845 : *
846 : * Returns:
847 : * - NB_OK on success.
848 : * - NB_ERR_NOT_FOUND when the element to be deleted was not found.
849 : * - NB_ERR for other errors.
850 : */
851 : extern int nb_candidate_edit(struct nb_config *candidate,
852 : const struct nb_node *nb_node,
853 : enum nb_operation operation, const char *xpath,
854 : const struct yang_data *previous,
855 : const struct yang_data *data);
856 :
857 : /*
858 : * Check if a candidate configuration is outdated and needs to be updated.
859 : *
860 : * candidate
861 : * Candidate configuration to check.
862 : *
863 : * Returns:
864 : * true if the candidate is outdated, false otherwise.
865 : */
866 : extern bool nb_candidate_needs_update(const struct nb_config *candidate);
867 :
868 : /*
869 : * Update a candidate configuration by rebasing the changes on top of the latest
870 : * running configuration. Resolve conflicts automatically by giving preference
871 : * to the changes done in the candidate configuration.
872 : *
873 : * candidate
874 : * Candidate configuration to update.
875 : *
876 : * Returns:
877 : * NB_OK on success, NB_ERR otherwise.
878 : */
879 : extern int nb_candidate_update(struct nb_config *candidate);
880 :
881 : /*
882 : * Validate a candidate configuration. Perform both YANG syntactic/semantic
883 : * validation and code-level validation using the northbound callbacks.
884 : *
885 : * WARNING: the candidate can be modified as part of the validation process
886 : * (e.g. add default nodes).
887 : *
888 : * context
889 : * Context of the northbound transaction.
890 : *
891 : * candidate
892 : * Candidate configuration to validate.
893 : *
894 : * errmsg
895 : * Buffer to store human-readable error message in case of error.
896 : *
897 : * errmsg_len
898 : * Size of errmsg.
899 : *
900 : * Returns:
901 : * NB_OK on success, NB_ERR_VALIDATION otherwise.
902 : */
903 : extern int nb_candidate_validate(struct nb_context *context,
904 : struct nb_config *candidate, char *errmsg,
905 : size_t errmsg_len);
906 :
907 : /*
908 : * Create a new configuration transaction but do not commit it yet. Only
909 : * validate the candidate and prepare all resources required to apply the
910 : * configuration changes.
911 : *
912 : * context
913 : * Context of the northbound transaction.
914 : *
915 : * candidate
916 : * Candidate configuration to commit.
917 : *
918 : * comment
919 : * Optional comment describing the commit.
920 : *
921 : * transaction
922 : * Output parameter providing the created transaction when one is created
923 : * successfully. In this case, it must be either aborted using
924 : * nb_candidate_commit_abort() or committed using
925 : * nb_candidate_commit_apply().
926 : *
927 : * errmsg
928 : * Buffer to store human-readable error message in case of error.
929 : *
930 : * errmsg_len
931 : * Size of errmsg.
932 : *
933 : * Returns:
934 : * - NB_OK on success.
935 : * - NB_ERR_NO_CHANGES when the candidate is identical to the running
936 : * configuration.
937 : * - NB_ERR_LOCKED when there's already another transaction in progress.
938 : * - NB_ERR_VALIDATION when the candidate fails the validation checks.
939 : * - NB_ERR_RESOURCE when the system fails to allocate resources to apply
940 : * the candidate configuration.
941 : * - NB_ERR for other errors.
942 : */
943 : extern int nb_candidate_commit_prepare(struct nb_context *context,
944 : struct nb_config *candidate,
945 : const char *comment,
946 : struct nb_transaction **transaction,
947 : char *errmsg, size_t errmsg_len);
948 :
949 : /*
950 : * Abort a previously created configuration transaction, releasing all resources
951 : * allocated during the preparation phase.
952 : *
953 : * transaction
954 : * Candidate configuration to abort. It's consumed by this function.
955 : *
956 : * errmsg
957 : * Buffer to store human-readable error message in case of error.
958 : *
959 : * errmsg_len
960 : * Size of errmsg.
961 : */
962 : extern void nb_candidate_commit_abort(struct nb_transaction *transaction,
963 : char *errmsg, size_t errmsg_len);
964 :
965 : /*
966 : * Commit a previously created configuration transaction.
967 : *
968 : * transaction
969 : * Configuration transaction to commit. It's consumed by this function.
970 : *
971 : * save_transaction
972 : * Specify whether the transaction should be recorded in the transactions log
973 : * or not.
974 : *
975 : * transaction_id
976 : * Optional output parameter providing the ID of the committed transaction.
977 : *
978 : * errmsg
979 : * Buffer to store human-readable error message in case of error.
980 : *
981 : * errmsg_len
982 : * Size of errmsg.
983 : */
984 : extern void nb_candidate_commit_apply(struct nb_transaction *transaction,
985 : bool save_transaction,
986 : uint32_t *transaction_id, char *errmsg,
987 : size_t errmsg_len);
988 :
989 : /*
990 : * Create a new transaction to commit a candidate configuration. This is a
991 : * convenience function that performs the two-phase commit protocol
992 : * transparently to the user. The cost is reduced flexibility, since
993 : * network-wide and multi-daemon transactions require the network manager to
994 : * take into account the results of the preparation phase of multiple managed
995 : * entities.
996 : *
997 : * context
998 : * Context of the northbound transaction.
999 : *
1000 : * candidate
1001 : * Candidate configuration to commit. It's preserved regardless if the commit
1002 : * operation fails or not.
1003 : *
1004 : * save_transaction
1005 : * Specify whether the transaction should be recorded in the transactions log
1006 : * or not.
1007 : *
1008 : * comment
1009 : * Optional comment describing the commit.
1010 : *
1011 : * transaction_id
1012 : * Optional output parameter providing the ID of the committed transaction.
1013 : *
1014 : * errmsg
1015 : * Buffer to store human-readable error message in case of error.
1016 : *
1017 : * errmsg_len
1018 : * Size of errmsg.
1019 : *
1020 : * Returns:
1021 : * - NB_OK on success.
1022 : * - NB_ERR_NO_CHANGES when the candidate is identical to the running
1023 : * configuration.
1024 : * - NB_ERR_LOCKED when there's already another transaction in progress.
1025 : * - NB_ERR_VALIDATION when the candidate fails the validation checks.
1026 : * - NB_ERR_RESOURCE when the system fails to allocate resources to apply
1027 : * the candidate configuration.
1028 : * - NB_ERR for other errors.
1029 : */
1030 : extern int nb_candidate_commit(struct nb_context *context,
1031 : struct nb_config *candidate,
1032 : bool save_transaction, const char *comment,
1033 : uint32_t *transaction_id, char *errmsg,
1034 : size_t errmsg_len);
1035 :
1036 : /*
1037 : * Lock the running configuration.
1038 : *
1039 : * client
1040 : * Northbound client.
1041 : *
1042 : * user
1043 : * Northbound user (can be NULL).
1044 : *
1045 : * Returns:
1046 : * 0 on success, -1 when the running configuration is already locked.
1047 : */
1048 : extern int nb_running_lock(enum nb_client client, const void *user);
1049 :
1050 : /*
1051 : * Unlock the running configuration.
1052 : *
1053 : * client
1054 : * Northbound client.
1055 : *
1056 : * user
1057 : * Northbound user (can be NULL).
1058 : *
1059 : * Returns:
1060 : * 0 on success, -1 when the running configuration is already unlocked or
1061 : * locked by another client/user.
1062 : */
1063 : extern int nb_running_unlock(enum nb_client client, const void *user);
1064 :
1065 : /*
1066 : * Check if the running configuration is locked or not for the given
1067 : * client/user.
1068 : *
1069 : * client
1070 : * Northbound client.
1071 : *
1072 : * user
1073 : * Northbound user (can be NULL).
1074 : *
1075 : * Returns:
1076 : * 0 if the running configuration is unlocked or if the client/user owns the
1077 : * lock, -1 otherwise.
1078 : */
1079 : extern int nb_running_lock_check(enum nb_client client, const void *user);
1080 :
1081 : /*
1082 : * Iterate over operational data.
1083 : *
1084 : * xpath
1085 : * Data path of the YANG data we want to iterate over.
1086 : *
1087 : * translator
1088 : * YANG module translator (might be NULL).
1089 : *
1090 : * flags
1091 : * NB_OPER_DATA_ITER_ flags to control how the iteration is performed.
1092 : *
1093 : * cb
1094 : * Function to call with each data node.
1095 : *
1096 : * arg
1097 : * Arbitrary argument passed as the fourth parameter in each call to 'cb'.
1098 : *
1099 : * Returns:
1100 : * NB_OK on success, NB_ERR otherwise.
1101 : */
1102 : extern int nb_oper_data_iterate(const char *xpath,
1103 : struct yang_translator *translator,
1104 : uint32_t flags, nb_oper_data_cb cb, void *arg);
1105 :
1106 : /*
1107 : * Validate if the northbound operation is valid for the given node.
1108 : *
1109 : * operation
1110 : * Operation we want to check.
1111 : *
1112 : * snode
1113 : * libyang schema node we want to check.
1114 : *
1115 : * Returns:
1116 : * true if the operation is valid, false otherwise.
1117 : */
1118 : extern bool nb_operation_is_valid(enum nb_operation operation,
1119 : const struct lysc_node *snode);
1120 :
1121 : /*
1122 : * Send a YANG notification. This is a no-op unless the 'nb_notification_send'
1123 : * hook was registered by a northbound plugin.
1124 : *
1125 : * xpath
1126 : * XPath of the YANG notification.
1127 : *
1128 : * arguments
1129 : * Linked list containing the arguments that should be sent. This list is
1130 : * deleted after being used.
1131 : *
1132 : * Returns:
1133 : * NB_OK on success, NB_ERR otherwise.
1134 : */
1135 : extern int nb_notification_send(const char *xpath, struct list *arguments);
1136 :
1137 : /*
1138 : * Associate a user pointer to a configuration node.
1139 : *
1140 : * This should be called by northbound 'create' callbacks in the NB_EV_APPLY
1141 : * phase only.
1142 : *
1143 : * dnode
1144 : * libyang data node - only its XPath is used.
1145 : *
1146 : * entry
1147 : * Arbitrary user-specified pointer.
1148 : */
1149 : extern void nb_running_set_entry(const struct lyd_node *dnode, void *entry);
1150 :
1151 : /*
1152 : * Move an entire tree of user pointer nodes.
1153 : *
1154 : * Suppose we have xpath A/B/C/D, with user pointers associated to C and D. We
1155 : * need to move B to be under Z, so the new xpath is Z/B/C/D. Because user
1156 : * pointers are indexed with their absolute path, We need to move all user
1157 : * pointers at and below B to their new absolute paths; this function does
1158 : * that.
1159 : *
1160 : * xpath_from
1161 : * base xpath of tree to move (A/B)
1162 : *
1163 : * xpath_to
1164 : * base xpath of new location of tree (Z/B)
1165 : */
1166 : extern void nb_running_move_tree(const char *xpath_from, const char *xpath_to);
1167 :
1168 : /*
1169 : * Unset the user pointer associated to a configuration node.
1170 : *
1171 : * This should be called by northbound 'destroy' callbacks in the NB_EV_APPLY
1172 : * phase only.
1173 : *
1174 : * dnode
1175 : * libyang data node - only its XPath is used.
1176 : *
1177 : * Returns:
1178 : * The user pointer that was unset.
1179 : */
1180 : extern void *nb_running_unset_entry(const struct lyd_node *dnode);
1181 :
1182 : /*
1183 : * Find the user pointer (if any) associated to a configuration node.
1184 : *
1185 : * The XPath associated to the configuration node can be provided directly or
1186 : * indirectly through a libyang data node.
1187 : *
1188 : * If an user point is not found, this function follows the parent nodes in the
1189 : * running configuration until an user pointer is found or until the root node
1190 : * is reached.
1191 : *
1192 : * dnode
1193 : * libyang data node - only its XPath is used (can be NULL if 'xpath' is
1194 : * provided).
1195 : *
1196 : * xpath
1197 : * XPath of the configuration node (can be NULL if 'dnode' is provided).
1198 : *
1199 : * abort_if_not_found
1200 : * When set to true, abort the program if no user pointer is found.
1201 : *
1202 : * As a rule of thumb, this parameter should be set to true in the following
1203 : * scenarios:
1204 : * - Calling this function from any northbound configuration callback during
1205 : * the NB_EV_APPLY phase.
1206 : * - Calling this function from a 'delete' northbound configuration callback
1207 : * during any phase.
1208 : *
1209 : * In both the above cases, the given configuration node should contain an
1210 : * user pointer except when there's a bug in the code, in which case it's
1211 : * better to abort the program right away and eliminate the need for
1212 : * unnecessary NULL checks.
1213 : *
1214 : * In all other cases, this parameter should be set to false and the caller
1215 : * should check if the function returned NULL or not.
1216 : *
1217 : * Returns:
1218 : * User pointer if found, NULL otherwise.
1219 : */
1220 : extern void *nb_running_get_entry(const struct lyd_node *dnode,
1221 : const char *xpath, bool abort_if_not_found);
1222 :
1223 : /*
1224 : * Same as 'nb_running_get_entry', but doesn't search within parent nodes
1225 : * recursively if an user point is not found.
1226 : */
1227 : extern void *nb_running_get_entry_non_rec(const struct lyd_node *dnode,
1228 : const char *xpath,
1229 : bool abort_if_not_found);
1230 :
1231 : /*
1232 : * Return a human-readable string representing a northbound event.
1233 : *
1234 : * event
1235 : * Northbound event.
1236 : *
1237 : * Returns:
1238 : * String representation of the given northbound event.
1239 : */
1240 : extern const char *nb_event_name(enum nb_event event);
1241 :
1242 : /*
1243 : * Return a human-readable string representing a northbound operation.
1244 : *
1245 : * operation
1246 : * Northbound operation.
1247 : *
1248 : * Returns:
1249 : * String representation of the given northbound operation.
1250 : */
1251 : extern const char *nb_operation_name(enum nb_operation operation);
1252 :
1253 : /*
1254 : * Return a human-readable string representing a northbound error.
1255 : *
1256 : * error
1257 : * Northbound error.
1258 : *
1259 : * Returns:
1260 : * String representation of the given northbound error.
1261 : */
1262 : extern const char *nb_err_name(enum nb_error error);
1263 :
1264 : /*
1265 : * Return a human-readable string representing a northbound client.
1266 : *
1267 : * client
1268 : * Northbound client.
1269 : *
1270 : * Returns:
1271 : * String representation of the given northbound client.
1272 : */
1273 : extern const char *nb_client_name(enum nb_client client);
1274 :
1275 : /*
1276 : * Validate all northbound callbacks.
1277 : *
1278 : * Some errors, like missing callbacks or invalid priorities, are fatal and
1279 : * can't be recovered from. Other errors, like unneeded callbacks, are logged
1280 : * but otherwise ignored.
1281 : *
1282 : * Whenever a YANG module is loaded after startup, *all* northbound callbacks
1283 : * need to be validated and not only the callbacks from the newly loaded module.
1284 : * This is because augmentations can change the properties of the augmented
1285 : * module, making mandatory the implementation of additional callbacks.
1286 : */
1287 : void nb_validate_callbacks(void);
1288 :
1289 : /*
1290 : * Initialize the northbound layer. Should be called only once during the
1291 : * daemon initialization process.
1292 : *
1293 : * modules
1294 : * Array of YANG modules to parse and initialize.
1295 : *
1296 : * nmodules
1297 : * Size of the modules array.
1298 : *
1299 : * db_enabled
1300 : * Set this to record the transactions in the transaction log.
1301 : */
1302 : extern void nb_init(struct thread_master *tm,
1303 : const struct frr_yang_module_info *const modules[],
1304 : size_t nmodules, bool db_enabled);
1305 :
1306 : /*
1307 : * Finish the northbound layer gracefully. Should be called only when the daemon
1308 : * is exiting.
1309 : */
1310 : extern void nb_terminate(void);
1311 :
1312 : #ifdef __cplusplus
1313 : }
1314 : #endif
1315 :
1316 : #endif /* _FRR_NORTHBOUND_H_ */
|