]> git.proxmox.com Git - mirror_frr.git/blob - tests/lib/northbound/test_oper_data.c
Merge pull request #6976 from achernavin22/rip_tools_key_chain_reloading
[mirror_frr.git] / tests / lib / northbound / test_oper_data.c
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 #include <zebra.h>
21
22 #include "thread.h"
23 #include "vty.h"
24 #include "command.h"
25 #include "memory.h"
26 #include "lib_vty.h"
27 #include "log.h"
28 #include "northbound.h"
29
30 static struct thread_master *master;
31
32 struct troute {
33 struct prefix_ipv4 prefix;
34 struct in_addr nexthop;
35 char ifname[IFNAMSIZ];
36 uint8_t metric;
37 bool active;
38 };
39
40 struct tvrf {
41 char name[32];
42 struct list *interfaces;
43 struct list *routes;
44 };
45
46 static struct list *vrfs;
47
48 /*
49 * XPath: /frr-test-module:frr-test-module/vrfs/vrf
50 */
51 static const void *
52 frr_test_module_vrfs_vrf_get_next(struct nb_cb_get_next_args *args)
53 {
54 struct listnode *node;
55
56 if (args->list_entry == NULL)
57 node = listhead(vrfs);
58 else
59 node = listnextnode((struct listnode *)args->list_entry);
60
61 return node;
62 }
63
64 static int frr_test_module_vrfs_vrf_get_keys(struct nb_cb_get_keys_args *args)
65 {
66 const struct tvrf *vrf;
67
68 vrf = listgetdata((struct listnode *)args->list_entry);
69
70 args->keys->num = 1;
71 strlcpy(args->keys->key[0], vrf->name, sizeof(args->keys->key[0]));
72
73 return NB_OK;
74 }
75
76 static const void *
77 frr_test_module_vrfs_vrf_lookup_entry(struct nb_cb_lookup_entry_args *args)
78 {
79 struct listnode *node;
80 struct tvrf *vrf;
81 const char *vrfname;
82
83 vrfname = args->keys->key[0];
84
85 for (ALL_LIST_ELEMENTS_RO(vrfs, node, vrf)) {
86 if (strmatch(vrf->name, vrfname))
87 return node;
88 }
89
90 return NULL;
91 }
92
93 /*
94 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/name
95 */
96 static struct yang_data *
97 frr_test_module_vrfs_vrf_name_get_elem(struct nb_cb_get_elem_args *args)
98 {
99 const struct tvrf *vrf;
100
101 vrf = listgetdata((struct listnode *)args->list_entry);
102 return yang_data_new_string(args->xpath, vrf->name);
103 }
104
105 /*
106 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/interfaces/interface
107 */
108 static struct yang_data *frr_test_module_vrfs_vrf_interfaces_interface_get_elem(
109 struct nb_cb_get_elem_args *args)
110 {
111 const char *interface;
112
113 interface = listgetdata((struct listnode *)args->list_entry);
114 return yang_data_new_string(args->xpath, interface);
115 }
116
117 static const void *frr_test_module_vrfs_vrf_interfaces_interface_get_next(
118 struct nb_cb_get_next_args *args)
119 {
120 const struct tvrf *vrf;
121 struct listnode *node;
122
123 vrf = listgetdata((struct listnode *)args->parent_list_entry);
124 if (args->list_entry == NULL)
125 node = listhead(vrf->interfaces);
126 else
127 node = listnextnode((struct listnode *)args->list_entry);
128
129 return node;
130 }
131
132 /*
133 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route
134 */
135 static const void *
136 frr_test_module_vrfs_vrf_routes_route_get_next(struct nb_cb_get_next_args *args)
137 {
138 const struct tvrf *vrf;
139 struct listnode *node;
140
141 vrf = listgetdata((struct listnode *)args->parent_list_entry);
142 if (args->list_entry == NULL)
143 node = listhead(vrf->routes);
144 else
145 node = listnextnode((struct listnode *)args->list_entry);
146
147 return node;
148 }
149
150 /*
151 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix
152 */
153 static struct yang_data *frr_test_module_vrfs_vrf_routes_route_prefix_get_elem(
154 struct nb_cb_get_elem_args *args)
155 {
156 const struct troute *route;
157
158 route = listgetdata((struct listnode *)args->list_entry);
159 return yang_data_new_ipv4p(args->xpath, &route->prefix);
160 }
161
162 /*
163 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop
164 */
165 static struct yang_data *
166 frr_test_module_vrfs_vrf_routes_route_next_hop_get_elem(
167 struct nb_cb_get_elem_args *args)
168 {
169 const struct troute *route;
170
171 route = listgetdata((struct listnode *)args->list_entry);
172 return yang_data_new_ipv4(args->xpath, &route->nexthop);
173 }
174
175 /*
176 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface
177 */
178 static struct yang_data *
179 frr_test_module_vrfs_vrf_routes_route_interface_get_elem(
180 struct nb_cb_get_elem_args *args)
181 {
182 const struct troute *route;
183
184 route = listgetdata((struct listnode *)args->list_entry);
185 return yang_data_new_string(args->xpath, route->ifname);
186 }
187
188 /*
189 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric
190 */
191 static struct yang_data *frr_test_module_vrfs_vrf_routes_route_metric_get_elem(
192 struct nb_cb_get_elem_args *args)
193 {
194 const struct troute *route;
195
196 route = listgetdata((struct listnode *)args->list_entry);
197 return yang_data_new_uint8(args->xpath, route->metric);
198 }
199
200 /*
201 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/active
202 */
203 static struct yang_data *frr_test_module_vrfs_vrf_routes_route_active_get_elem(
204 struct nb_cb_get_elem_args *args)
205 {
206 const struct troute *route;
207
208 route = listgetdata((struct listnode *)args->list_entry);
209 if (route->active)
210 return yang_data_new(args->xpath, NULL);
211
212 return NULL;
213 }
214
215 /* clang-format off */
216 const struct frr_yang_module_info frr_test_module_info = {
217 .name = "frr-test-module",
218 .nodes = {
219 {
220 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf",
221 .cbs.get_next = frr_test_module_vrfs_vrf_get_next,
222 .cbs.get_keys = frr_test_module_vrfs_vrf_get_keys,
223 .cbs.lookup_entry = frr_test_module_vrfs_vrf_lookup_entry,
224 },
225 {
226 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/name",
227 .cbs.get_elem = frr_test_module_vrfs_vrf_name_get_elem,
228 },
229 {
230 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/interfaces/interface",
231 .cbs.get_elem = frr_test_module_vrfs_vrf_interfaces_interface_get_elem,
232 .cbs.get_next = frr_test_module_vrfs_vrf_interfaces_interface_get_next,
233 },
234 {
235 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/routes/route",
236 .cbs.get_next = frr_test_module_vrfs_vrf_routes_route_get_next,
237 },
238 {
239 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix",
240 .cbs.get_elem = frr_test_module_vrfs_vrf_routes_route_prefix_get_elem,
241 },
242 {
243 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop",
244 .cbs.get_elem = frr_test_module_vrfs_vrf_routes_route_next_hop_get_elem,
245 },
246 {
247 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface",
248 .cbs.get_elem = frr_test_module_vrfs_vrf_routes_route_interface_get_elem,
249 },
250 {
251 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric",
252 .cbs.get_elem = frr_test_module_vrfs_vrf_routes_route_metric_get_elem,
253 },
254 {
255 .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/active",
256 .cbs.get_elem = frr_test_module_vrfs_vrf_routes_route_active_get_elem,
257 },
258 {
259 .xpath = NULL,
260 },
261 }
262 };
263 /* clang-format on */
264
265 static const struct frr_yang_module_info *const modules[] = {
266 &frr_test_module_info,
267 };
268
269 static void create_data(unsigned int num_vrfs, unsigned int num_interfaces,
270 unsigned int num_routes)
271 {
272 struct prefix_ipv4 base_prefix;
273 struct in_addr base_nexthop;
274
275 (void)str2prefix_ipv4("10.0.0.0/32", &base_prefix);
276 (void)inet_pton(AF_INET, "172.16.0.0", &base_nexthop);
277
278 vrfs = list_new();
279
280 /* Create VRFs. */
281 for (unsigned int i = 0; i < num_vrfs; i++) {
282 struct tvrf *vrf;
283
284 vrf = XCALLOC(MTYPE_TMP, sizeof(*vrf));
285 snprintf(vrf->name, sizeof(vrf->name), "vrf%u", i);
286 vrf->interfaces = list_new();
287 vrf->routes = list_new();
288
289 /* Create interfaces. */
290 for (unsigned int j = 0; j < num_interfaces; j++) {
291 char ifname[32];
292 char *interface;
293
294 snprintf(ifname, sizeof(ifname), "eth%u", j);
295 interface = XSTRDUP(MTYPE_TMP, ifname);
296 listnode_add(vrf->interfaces, interface);
297 }
298
299 /* Create routes. */
300 for (unsigned int j = 0; j < num_routes; j++) {
301 struct troute *route;
302
303 route = XCALLOC(MTYPE_TMP, sizeof(*route));
304
305 memcpy(&route->prefix, &base_prefix,
306 sizeof(route->prefix));
307 route->prefix.prefix.s_addr =
308 htonl(ntohl(route->prefix.prefix.s_addr) + j);
309
310 memcpy(&route->nexthop, &base_nexthop,
311 sizeof(route->nexthop));
312 route->nexthop.s_addr =
313 htonl(ntohl(route->nexthop.s_addr) + j);
314
315 snprintf(route->ifname, sizeof(route->ifname), "eth%u",
316 j);
317 route->metric = j % 256;
318 route->active = (j % 2 == 0);
319 listnode_add(vrf->routes, route);
320 }
321
322 listnode_add(vrfs, vrf);
323 }
324 }
325
326 static void interface_delete(void *ptr)
327 {
328 char *interface = ptr;
329
330 XFREE(MTYPE_TMP, interface);
331 }
332
333 static void route_delete(void *ptr)
334 {
335 struct troute *route = ptr;
336
337 XFREE(MTYPE_TMP, route);
338 }
339
340 static void vrf_delete(void *ptr)
341 {
342 struct tvrf *vrf = ptr;
343
344 vrf->interfaces->del = interface_delete;
345 list_delete(&vrf->interfaces);
346 vrf->routes->del = route_delete;
347 list_delete(&vrf->routes);
348 XFREE(MTYPE_TMP, vrf);
349 }
350
351 static void delete_data(void)
352 {
353 vrfs->del = vrf_delete;
354 list_delete(&vrfs);
355 }
356
357 static void vty_do_exit(int isexit)
358 {
359 printf("\nend.\n");
360
361 delete_data();
362
363 cmd_terminate();
364 vty_terminate();
365 nb_terminate();
366 yang_terminate();
367 thread_master_free(master);
368
369 log_memstats(stderr, "test-nb-oper-data");
370 if (!isexit)
371 exit(0);
372 }
373
374 /* main routine. */
375 int main(int argc, char **argv)
376 {
377 struct thread thread;
378 unsigned int num_vrfs = 2;
379 unsigned int num_interfaces = 4;
380 unsigned int num_routes = 6;
381
382 if (argc > 1)
383 num_vrfs = atoi(argv[1]);
384 if (argc > 2)
385 num_interfaces = atoi(argv[2]);
386 if (argc > 3)
387 num_routes = atoi(argv[3]);
388
389 /* Set umask before anything for security */
390 umask(0027);
391
392 /* master init. */
393 master = thread_master_create(NULL);
394
395 zlog_aux_init("NONE: ", ZLOG_DISABLED);
396
397 /* Library inits. */
398 cmd_init(1);
399 cmd_hostname_set("test");
400 vty_init(master, false);
401 lib_cmd_init();
402 yang_init(true);
403 nb_init(master, modules, array_size(modules), false);
404
405 /* Create artificial data. */
406 create_data(num_vrfs, num_interfaces, num_routes);
407
408 /* Read input from .in file. */
409 vty_stdio(vty_do_exit);
410
411 /* Fetch next active thread. */
412 while (thread_fetch(master, &thread))
413 thread_call(&thread);
414
415 /* Not reached. */
416 exit(0);
417 }