back to topotato report
topotato coverage report
Current view: top level - lib - northbound.h (source / functions) Hit Total Coverage
Test: test_pim6_prune_propagate.py::PIM6PrunePropagate Lines: 1 1 100.0 %
Date: 2023-02-24 18:39:23 Functions: 0 0 -

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

Generated by: LCOV version v1.16-topotato