2 * Copyright (C) 2018 NetDEF, Inc.
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)
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
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
26 #include "memory_vty.h"
28 #include "northbound.h"
30 static struct thread_master
*master
;
33 struct prefix_ipv4 prefix
;
34 struct in_addr nexthop
;
35 char ifname
[IFNAMSIZ
];
42 struct list
*interfaces
;
46 static struct list
*vrfs
;
49 * XPath: /frr-test-module:frr-test-module/vrfs/vrf
52 frr_test_module_vrfs_vrf_get_next(const void *parent_list_entry
,
53 const void *list_entry
)
55 struct listnode
*node
;
57 if (list_entry
== NULL
)
58 node
= listhead(vrfs
);
60 node
= listnextnode((struct listnode
*)list_entry
);
65 static int frr_test_module_vrfs_vrf_get_keys(const void *list_entry
,
66 struct yang_list_keys
*keys
)
68 const struct tvrf
*vrf
;
70 vrf
= listgetdata((struct listnode
*)list_entry
);
73 strlcpy(keys
->key
[0], vrf
->name
, sizeof(keys
->key
[0]));
79 frr_test_module_vrfs_vrf_lookup_entry(const void *parent_list_entry
,
80 const struct yang_list_keys
*keys
)
82 struct listnode
*node
;
86 vrfname
= keys
->key
[0];
88 for (ALL_LIST_ELEMENTS_RO(vrfs
, node
, vrf
)) {
89 if (strmatch(vrf
->name
, vrfname
))
97 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/name
99 static struct yang_data
*
100 frr_test_module_vrfs_vrf_name_get_elem(const char *xpath
,
101 const void *list_entry
)
103 const struct tvrf
*vrf
;
105 vrf
= listgetdata((struct listnode
*)list_entry
);
106 return yang_data_new_string(xpath
, vrf
->name
);
110 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/interfaces/interface
112 static struct yang_data
*
113 frr_test_module_vrfs_vrf_interfaces_interface_get_elem(const char *xpath
,
114 const void *list_entry
)
116 const char *interface
;
118 interface
= listgetdata((struct listnode
*)list_entry
);
119 return yang_data_new_string(xpath
, interface
);
122 static const void *frr_test_module_vrfs_vrf_interfaces_interface_get_next(
123 const void *parent_list_entry
, const void *list_entry
)
125 const struct tvrf
*vrf
;
126 struct listnode
*node
;
128 vrf
= listgetdata((struct listnode
*)parent_list_entry
);
129 if (list_entry
== NULL
)
130 node
= listhead(vrf
->interfaces
);
132 node
= listnextnode((struct listnode
*)list_entry
);
138 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route
141 frr_test_module_vrfs_vrf_routes_route_get_next(const void *parent_list_entry
,
142 const void *list_entry
)
144 const struct tvrf
*vrf
;
145 struct listnode
*node
;
147 vrf
= listgetdata((struct listnode
*)parent_list_entry
);
148 if (list_entry
== NULL
)
149 node
= listhead(vrf
->routes
);
151 node
= listnextnode((struct listnode
*)list_entry
);
157 frr_test_module_vrfs_vrf_routes_route_get_keys(const void *list_entry
,
158 struct yang_list_keys
*keys
)
160 const struct troute
*route
;
162 route
= listgetdata((struct listnode
*)list_entry
);
165 (void)prefix2str(&route
->prefix
, keys
->key
[0], sizeof(keys
->key
[0]));
170 static const void *frr_test_module_vrfs_vrf_routes_route_lookup_entry(
171 const void *parent_list_entry
, const struct yang_list_keys
*keys
)
173 const struct tvrf
*vrf
;
174 const struct troute
*route
;
175 struct listnode
*node
;
176 struct prefix prefix
;
178 yang_str2ipv4p(keys
->key
[0], &prefix
);
180 vrf
= listgetdata((struct listnode
*)parent_list_entry
);
181 for (ALL_LIST_ELEMENTS_RO(vrf
->routes
, node
, route
)) {
182 if (prefix_same((struct prefix
*)&route
->prefix
, &prefix
))
190 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix
192 static struct yang_data
*
193 frr_test_module_vrfs_vrf_routes_route_prefix_get_elem(const char *xpath
,
194 const void *list_entry
)
196 const struct troute
*route
;
198 route
= listgetdata((struct listnode
*)list_entry
);
199 return yang_data_new_ipv4p(xpath
, &route
->prefix
);
203 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop
205 static struct yang_data
*
206 frr_test_module_vrfs_vrf_routes_route_next_hop_get_elem(const char *xpath
,
207 const void *list_entry
)
209 const struct troute
*route
;
211 route
= listgetdata((struct listnode
*)list_entry
);
212 return yang_data_new_ipv4(xpath
, &route
->nexthop
);
216 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface
218 static struct yang_data
*
219 frr_test_module_vrfs_vrf_routes_route_interface_get_elem(const char *xpath
,
220 const void *list_entry
)
222 const struct troute
*route
;
224 route
= listgetdata((struct listnode
*)list_entry
);
225 return yang_data_new_string(xpath
, route
->ifname
);
229 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric
231 static struct yang_data
*
232 frr_test_module_vrfs_vrf_routes_route_metric_get_elem(const char *xpath
,
233 const void *list_entry
)
235 const struct troute
*route
;
237 route
= listgetdata((struct listnode
*)list_entry
);
238 return yang_data_new_uint8(xpath
, route
->metric
);
242 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/active
244 static struct yang_data
*
245 frr_test_module_vrfs_vrf_routes_route_active_get_elem(const char *xpath
,
246 const void *list_entry
)
248 const struct troute
*route
;
250 route
= listgetdata((struct listnode
*)list_entry
);
252 return yang_data_new(xpath
, NULL
);
257 /* clang-format off */
258 const struct frr_yang_module_info frr_test_module_info
= {
259 .name
= "frr-test-module",
262 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf",
263 .cbs
.get_next
= frr_test_module_vrfs_vrf_get_next
,
264 .cbs
.get_keys
= frr_test_module_vrfs_vrf_get_keys
,
265 .cbs
.lookup_entry
= frr_test_module_vrfs_vrf_lookup_entry
,
268 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/name",
269 .cbs
.get_elem
= frr_test_module_vrfs_vrf_name_get_elem
,
272 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/interfaces/interface",
273 .cbs
.get_elem
= frr_test_module_vrfs_vrf_interfaces_interface_get_elem
,
274 .cbs
.get_next
= frr_test_module_vrfs_vrf_interfaces_interface_get_next
,
277 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route",
278 .cbs
.get_next
= frr_test_module_vrfs_vrf_routes_route_get_next
,
279 .cbs
.get_keys
= frr_test_module_vrfs_vrf_routes_route_get_keys
,
280 .cbs
.lookup_entry
= frr_test_module_vrfs_vrf_routes_route_lookup_entry
,
283 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix",
284 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_prefix_get_elem
,
287 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop",
288 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_next_hop_get_elem
,
291 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface",
292 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_interface_get_elem
,
295 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric",
296 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_metric_get_elem
,
299 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/active",
300 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_active_get_elem
,
307 /* clang-format on */
309 static const struct frr_yang_module_info
*modules
[] = {
310 &frr_test_module_info
,
313 static void create_data(unsigned int num_vrfs
, unsigned int num_interfaces
,
314 unsigned int num_routes
)
316 struct prefix_ipv4 base_prefix
;
317 struct in_addr base_nexthop
;
319 (void)str2prefix_ipv4("10.0.0.0/32", &base_prefix
);
320 (void)inet_pton(AF_INET
, "172.16.0.0", &base_nexthop
);
325 for (unsigned int i
= 0; i
< num_vrfs
; i
++) {
328 vrf
= XCALLOC(MTYPE_TMP
, sizeof(*vrf
));
329 snprintf(vrf
->name
, sizeof(vrf
->name
), "vrf%u", i
);
330 vrf
->interfaces
= list_new();
331 vrf
->routes
= list_new();
333 /* Create interfaces. */
334 for (unsigned int j
= 0; j
< num_interfaces
; j
++) {
338 snprintf(ifname
, sizeof(ifname
), "eth%u", j
);
339 interface
= XSTRDUP(MTYPE_TMP
, ifname
);
340 listnode_add(vrf
->interfaces
, interface
);
344 for (unsigned int j
= 0; j
< num_routes
; j
++) {
345 struct troute
*route
;
347 route
= XCALLOC(MTYPE_TMP
, sizeof(*route
));
349 memcpy(&route
->prefix
, &base_prefix
,
350 sizeof(route
->prefix
));
351 route
->prefix
.prefix
.s_addr
=
352 htonl(ntohl(route
->prefix
.prefix
.s_addr
) + j
);
354 memcpy(&route
->nexthop
, &base_nexthop
,
355 sizeof(route
->nexthop
));
356 route
->nexthop
.s_addr
=
357 htonl(ntohl(route
->nexthop
.s_addr
) + j
);
359 snprintf(route
->ifname
, sizeof(route
->ifname
), "eth%u",
361 route
->metric
= j
% 256;
362 route
->active
= (j
% 2 == 0);
363 listnode_add(vrf
->routes
, route
);
366 listnode_add(vrfs
, vrf
);
370 static void interface_delete(void *ptr
)
372 char *interface
= ptr
;
374 XFREE(MTYPE_TMP
, interface
);
377 static void route_delete(void *ptr
)
379 struct troute
*route
= ptr
;
381 XFREE(MTYPE_TMP
, route
);
384 static void vrf_delete(void *ptr
)
386 struct tvrf
*vrf
= ptr
;
388 vrf
->interfaces
->del
= interface_delete
;
389 list_delete(&vrf
->interfaces
);
390 vrf
->routes
->del
= route_delete
;
391 list_delete(&vrf
->routes
);
392 XFREE(MTYPE_TMP
, vrf
);
395 static void delete_data(void)
397 vrfs
->del
= vrf_delete
;
401 static void vty_do_exit(int isexit
)
411 thread_master_free(master
);
414 log_memstats(stderr
, "test-nb-oper-data");
420 int main(int argc
, char **argv
)
422 struct thread thread
;
423 unsigned int num_vrfs
= 2;
424 unsigned int num_interfaces
= 4;
425 unsigned int num_routes
= 6;
428 num_vrfs
= atoi(argv
[1]);
430 num_interfaces
= atoi(argv
[2]);
432 num_routes
= atoi(argv
[3]);
434 /* Set umask before anything for security */
438 master
= thread_master_create(NULL
);
440 openzlog("test-nb-oper-data", "NONE", 0,
441 LOG_CONS
| LOG_NDELAY
| LOG_PID
, LOG_DAEMON
);
442 zlog_set_level(ZLOG_DEST_SYSLOG
, ZLOG_DISABLED
);
443 zlog_set_level(ZLOG_DEST_STDOUT
, ZLOG_DISABLED
);
444 zlog_set_level(ZLOG_DEST_MONITOR
, LOG_DEBUG
);
448 cmd_hostname_set("test");
452 nb_init(master
, modules
, array_size(modules
));
454 /* Create artificial data. */
455 create_data(num_vrfs
, num_interfaces
, num_routes
);
457 /* Read input from .in file. */
458 vty_stdio(vty_do_exit
);
460 /* Fetch next active thread. */
461 while (thread_fetch(master
, &thread
))
462 thread_call(&thread
);