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
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 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix
159 static struct yang_data
*
160 frr_test_module_vrfs_vrf_routes_route_prefix_get_elem(const char *xpath
,
161 const void *list_entry
)
163 const struct troute
*route
;
165 route
= listgetdata((struct listnode
*)list_entry
);
166 return yang_data_new_ipv4p(xpath
, &route
->prefix
);
170 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop
172 static struct yang_data
*
173 frr_test_module_vrfs_vrf_routes_route_next_hop_get_elem(const char *xpath
,
174 const void *list_entry
)
176 const struct troute
*route
;
178 route
= listgetdata((struct listnode
*)list_entry
);
179 return yang_data_new_ipv4(xpath
, &route
->nexthop
);
183 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface
185 static struct yang_data
*
186 frr_test_module_vrfs_vrf_routes_route_interface_get_elem(const char *xpath
,
187 const void *list_entry
)
189 const struct troute
*route
;
191 route
= listgetdata((struct listnode
*)list_entry
);
192 return yang_data_new_string(xpath
, route
->ifname
);
196 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric
198 static struct yang_data
*
199 frr_test_module_vrfs_vrf_routes_route_metric_get_elem(const char *xpath
,
200 const void *list_entry
)
202 const struct troute
*route
;
204 route
= listgetdata((struct listnode
*)list_entry
);
205 return yang_data_new_uint8(xpath
, route
->metric
);
209 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/active
211 static struct yang_data
*
212 frr_test_module_vrfs_vrf_routes_route_active_get_elem(const char *xpath
,
213 const void *list_entry
)
215 const struct troute
*route
;
217 route
= listgetdata((struct listnode
*)list_entry
);
219 return yang_data_new(xpath
, NULL
);
224 /* clang-format off */
225 const struct frr_yang_module_info frr_test_module_info
= {
226 .name
= "frr-test-module",
229 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf",
230 .cbs
.get_next
= frr_test_module_vrfs_vrf_get_next
,
231 .cbs
.get_keys
= frr_test_module_vrfs_vrf_get_keys
,
232 .cbs
.lookup_entry
= frr_test_module_vrfs_vrf_lookup_entry
,
235 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/name",
236 .cbs
.get_elem
= frr_test_module_vrfs_vrf_name_get_elem
,
239 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/interfaces/interface",
240 .cbs
.get_elem
= frr_test_module_vrfs_vrf_interfaces_interface_get_elem
,
241 .cbs
.get_next
= frr_test_module_vrfs_vrf_interfaces_interface_get_next
,
244 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route",
245 .cbs
.get_next
= frr_test_module_vrfs_vrf_routes_route_get_next
,
248 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix",
249 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_prefix_get_elem
,
252 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop",
253 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_next_hop_get_elem
,
256 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface",
257 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_interface_get_elem
,
260 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric",
261 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_metric_get_elem
,
264 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/active",
265 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_active_get_elem
,
272 /* clang-format on */
274 static const struct frr_yang_module_info
*const modules
[] = {
275 &frr_test_module_info
,
278 static void create_data(unsigned int num_vrfs
, unsigned int num_interfaces
,
279 unsigned int num_routes
)
281 struct prefix_ipv4 base_prefix
;
282 struct in_addr base_nexthop
;
284 (void)str2prefix_ipv4("10.0.0.0/32", &base_prefix
);
285 (void)inet_pton(AF_INET
, "172.16.0.0", &base_nexthop
);
290 for (unsigned int i
= 0; i
< num_vrfs
; i
++) {
293 vrf
= XCALLOC(MTYPE_TMP
, sizeof(*vrf
));
294 snprintf(vrf
->name
, sizeof(vrf
->name
), "vrf%u", i
);
295 vrf
->interfaces
= list_new();
296 vrf
->routes
= list_new();
298 /* Create interfaces. */
299 for (unsigned int j
= 0; j
< num_interfaces
; j
++) {
303 snprintf(ifname
, sizeof(ifname
), "eth%u", j
);
304 interface
= XSTRDUP(MTYPE_TMP
, ifname
);
305 listnode_add(vrf
->interfaces
, interface
);
309 for (unsigned int j
= 0; j
< num_routes
; j
++) {
310 struct troute
*route
;
312 route
= XCALLOC(MTYPE_TMP
, sizeof(*route
));
314 memcpy(&route
->prefix
, &base_prefix
,
315 sizeof(route
->prefix
));
316 route
->prefix
.prefix
.s_addr
=
317 htonl(ntohl(route
->prefix
.prefix
.s_addr
) + j
);
319 memcpy(&route
->nexthop
, &base_nexthop
,
320 sizeof(route
->nexthop
));
321 route
->nexthop
.s_addr
=
322 htonl(ntohl(route
->nexthop
.s_addr
) + j
);
324 snprintf(route
->ifname
, sizeof(route
->ifname
), "eth%u",
326 route
->metric
= j
% 256;
327 route
->active
= (j
% 2 == 0);
328 listnode_add(vrf
->routes
, route
);
331 listnode_add(vrfs
, vrf
);
335 static void interface_delete(void *ptr
)
337 char *interface
= ptr
;
339 XFREE(MTYPE_TMP
, interface
);
342 static void route_delete(void *ptr
)
344 struct troute
*route
= ptr
;
346 XFREE(MTYPE_TMP
, route
);
349 static void vrf_delete(void *ptr
)
351 struct tvrf
*vrf
= ptr
;
353 vrf
->interfaces
->del
= interface_delete
;
354 list_delete(&vrf
->interfaces
);
355 vrf
->routes
->del
= route_delete
;
356 list_delete(&vrf
->routes
);
357 XFREE(MTYPE_TMP
, vrf
);
360 static void delete_data(void)
362 vrfs
->del
= vrf_delete
;
366 static void vty_do_exit(int isexit
)
376 thread_master_free(master
);
379 log_memstats(stderr
, "test-nb-oper-data");
385 int main(int argc
, char **argv
)
387 struct thread thread
;
388 unsigned int num_vrfs
= 2;
389 unsigned int num_interfaces
= 4;
390 unsigned int num_routes
= 6;
393 num_vrfs
= atoi(argv
[1]);
395 num_interfaces
= atoi(argv
[2]);
397 num_routes
= atoi(argv
[3]);
399 /* Set umask before anything for security */
403 master
= thread_master_create(NULL
);
405 openzlog("test-nb-oper-data", "NONE", 0,
406 LOG_CONS
| LOG_NDELAY
| LOG_PID
, LOG_DAEMON
);
407 zlog_set_level(ZLOG_DEST_SYSLOG
, ZLOG_DISABLED
);
408 zlog_set_level(ZLOG_DEST_STDOUT
, ZLOG_DISABLED
);
409 zlog_set_level(ZLOG_DEST_MONITOR
, LOG_DEBUG
);
413 cmd_hostname_set("test");
414 vty_init(master
, false);
417 nb_init(master
, modules
, array_size(modules
));
419 /* Create artificial data. */
420 create_data(num_vrfs
, num_interfaces
, num_routes
);
422 /* Read input from .in file. */
423 vty_stdio(vty_do_exit
);
425 /* Fetch next active thread. */
426 while (thread_fetch(master
, &thread
))
427 thread_call(&thread
);