]>
git.proxmox.com Git - mirror_frr.git/blob - tools/gen_northbound_callbacks.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2018 NetDEF, Inc.
7 #define REALLY_NEED_PLAIN_GETOPT 1
14 #include "northbound.h"
16 static bool static_cbs
;
18 static void __attribute__((noreturn
)) usage(int status
)
20 extern const char *__progname
;
21 fprintf(stderr
, "usage: %s [-h] [-s] [-p path] MODULE\n", __progname
);
25 static struct nb_callback_info
{
29 char return_value
[32];
33 .operation
= NB_OP_CREATE
,
34 .return_type
= "int ",
35 .return_value
= "NB_OK",
36 .arguments
= "struct nb_cb_create_args *args",
39 .operation
= NB_OP_MODIFY
,
40 .return_type
= "int ",
41 .return_value
= "NB_OK",
42 .arguments
= "struct nb_cb_modify_args *args",
45 .operation
= NB_OP_DESTROY
,
46 .return_type
= "int ",
47 .return_value
= "NB_OK",
48 .arguments
= "struct nb_cb_destroy_args *args",
51 .operation
= NB_OP_MOVE
,
52 .return_type
= "int ",
53 .return_value
= "NB_OK",
54 .arguments
= "struct nb_cb_move_args *args",
57 .operation
= NB_OP_APPLY_FINISH
,
59 .return_type
= "void ",
61 .arguments
= "struct nb_cb_apply_finish_args *args",
64 .operation
= NB_OP_GET_ELEM
,
65 .return_type
= "struct yang_data *",
66 .return_value
= "NULL",
67 .arguments
= "struct nb_cb_get_elem_args *args",
70 .operation
= NB_OP_GET_NEXT
,
71 .return_type
= "const void *",
72 .return_value
= "NULL",
73 .arguments
= "struct nb_cb_get_next_args *args",
76 .operation
= NB_OP_GET_KEYS
,
77 .return_type
= "int ",
78 .return_value
= "NB_OK",
79 .arguments
= "struct nb_cb_get_keys_args *args",
82 .operation
= NB_OP_LOOKUP_ENTRY
,
83 .return_type
= "const void *",
84 .return_value
= "NULL",
85 .arguments
= "struct nb_cb_lookup_entry_args *args",
88 .operation
= NB_OP_RPC
,
89 .return_type
= "int ",
90 .return_value
= "NB_OK",
91 .arguments
= "struct nb_cb_rpc_args *args",
99 static void replace_hyphens_by_underscores(char *str
)
104 while ((p
= strchr(p
, '-')) != NULL
)
108 static void generate_callback_name(const struct lysc_node
*snode
,
109 enum nb_operation operation
, char *buffer
,
116 for (; snode
; snode
= snode
->parent
) {
117 /* Skip schema-only snodes. */
118 if (CHECK_FLAG(snode
->nodetype
, LYS_USES
| LYS_CHOICE
| LYS_CASE
123 listnode_add_head(snodes
, (void *)snode
);
126 memset(buffer
, 0, size
);
127 for (ALL_LIST_ELEMENTS_RO(snodes
, ln
, snode
)) {
128 strlcat(buffer
, snode
->name
, size
);
129 strlcat(buffer
, "_", size
);
131 strlcat(buffer
, nb_operation_name(operation
), size
);
132 list_delete(&snodes
);
134 replace_hyphens_by_underscores(buffer
);
137 static void generate_prototype(const struct nb_callback_info
*ncinfo
,
140 printf("%s%s(%s);\n", ncinfo
->return_type
, cb_name
, ncinfo
->arguments
);
143 static int generate_prototypes(const struct lysc_node
*snode
, void *arg
)
145 switch (snode
->nodetype
) {
154 return YANG_ITER_CONTINUE
;
157 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
158 cb
->operation
!= -1; cb
++) {
159 char cb_name
[BUFSIZ
];
162 || !nb_operation_is_valid(cb
->operation
, snode
))
165 generate_callback_name(snode
, cb
->operation
, cb_name
,
167 generate_prototype(cb
, cb_name
);
170 return YANG_ITER_CONTINUE
;
173 static void generate_callback(const struct nb_callback_info
*ncinfo
,
176 printf("%s%s%s(%s)\n{\n", static_cbs
? "static " : "",
177 ncinfo
->return_type
, cb_name
, ncinfo
->arguments
);
179 switch (ncinfo
->operation
) {
184 printf("\tswitch (args->event) {\n"
185 "\tcase NB_EV_VALIDATE:\n"
186 "\tcase NB_EV_PREPARE:\n"
187 "\tcase NB_EV_ABORT:\n"
188 "\tcase NB_EV_APPLY:\n"
189 "\t\t/* TODO: implement me. */\n"
196 printf("\t/* TODO: implement me. */\n");
200 printf("\treturn %s;\n}\n\n", ncinfo
->return_value
);
203 static int generate_callbacks(const struct lysc_node
*snode
, void *arg
)
207 switch (snode
->nodetype
) {
216 return YANG_ITER_CONTINUE
;
219 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
220 cb
->operation
!= -1; cb
++) {
221 char cb_name
[BUFSIZ
];
224 || !nb_operation_is_valid(cb
->operation
, snode
))
228 char xpath
[XPATH_MAXLEN
];
230 yang_snode_get_path(snode
, YANG_PATH_DATA
, xpath
,
240 generate_callback_name(snode
, cb
->operation
, cb_name
,
242 generate_callback(cb
, cb_name
);
245 return YANG_ITER_CONTINUE
;
248 static int generate_nb_nodes(const struct lysc_node
*snode
, void *arg
)
252 switch (snode
->nodetype
) {
261 return YANG_ITER_CONTINUE
;
264 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
265 cb
->operation
!= -1; cb
++) {
266 char cb_name
[BUFSIZ
];
269 || !nb_operation_is_valid(cb
->operation
, snode
))
273 char xpath
[XPATH_MAXLEN
];
275 yang_snode_get_path(snode
, YANG_PATH_DATA
, xpath
,
279 "\t\t\t.xpath = \"%s\",\n",
281 printf("\t\t\t.cbs = {\n");
285 generate_callback_name(snode
, cb
->operation
, cb_name
,
287 printf("\t\t\t\t.%s = %s,\n", nb_operation_name(cb
->operation
),
296 return YANG_ITER_CONTINUE
;
299 int main(int argc
, char *argv
[])
301 const char *search_path
= NULL
;
302 struct yang_module
*module
;
303 char module_name_underscores
[64];
307 while ((opt
= getopt(argc
, argv
, "hp:s")) != -1) {
313 if (stat(optarg
, &st
) == -1) {
315 "error: invalid search path '%s': %s\n",
316 optarg
, strerror(errno
));
319 if (S_ISDIR(st
.st_mode
) == 0) {
321 "error: search path is not directory");
325 search_path
= optarg
;
340 yang_init(false, true);
343 ly_ctx_set_searchdir(ly_native_ctx
, search_path
);
345 /* Load all FRR native models to ensure all augmentations are loaded. */
346 yang_module_load_all();
348 module
= yang_module_find(argv
[0]);
350 /* Non-native FRR module (e.g. modules from unit tests). */
351 module
= yang_module_load(argv
[0]);
353 yang_init_loading_complete();
355 /* Create a nb_node for all YANG schema nodes. */
358 /* Generate callback prototypes. */
360 printf("/* prototypes */\n");
361 yang_snodes_iterate(module
->info
, generate_prototypes
, 0, NULL
);
365 /* Generate callback functions. */
366 yang_snodes_iterate(module
->info
, generate_callbacks
, 0, NULL
);
368 strlcpy(module_name_underscores
, module
->name
,
369 sizeof(module_name_underscores
));
370 replace_hyphens_by_underscores(module_name_underscores
);
372 /* Generate frr_yang_module_info array. */
373 printf("/* clang-format off */\n"
374 "const struct frr_yang_module_info %s_info = {\n"
375 "\t.name = \"%s\",\n"
377 module_name_underscores
, module
->name
);
378 yang_snodes_iterate(module
->info
, generate_nb_nodes
, 0, NULL
);
380 "\t\t\t.xpath = NULL,\n"
385 /* Cleanup and exit. */