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