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