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(struct nb_cb_get_next_args
*args
)
54 struct listnode
*node
;
56 if (args
->list_entry
== NULL
)
57 node
= listhead(vrfs
);
59 node
= listnextnode((struct listnode
*)args
->list_entry
);
64 static int frr_test_module_vrfs_vrf_get_keys(struct nb_cb_get_keys_args
*args
)
66 const struct tvrf
*vrf
;
68 vrf
= listgetdata((struct listnode
*)args
->list_entry
);
71 strlcpy(args
->keys
->key
[0], vrf
->name
, sizeof(args
->keys
->key
[0]));
77 frr_test_module_vrfs_vrf_lookup_entry(struct nb_cb_lookup_entry_args
*args
)
79 struct listnode
*node
;
83 vrfname
= args
->keys
->key
[0];
85 for (ALL_LIST_ELEMENTS_RO(vrfs
, node
, vrf
)) {
86 if (strmatch(vrf
->name
, vrfname
))
94 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/name
96 static struct yang_data
*
97 frr_test_module_vrfs_vrf_name_get_elem(struct nb_cb_get_elem_args
*args
)
99 const struct tvrf
*vrf
;
101 vrf
= listgetdata((struct listnode
*)args
->list_entry
);
102 return yang_data_new_string(args
->xpath
, vrf
->name
);
106 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/interfaces/interface
108 static struct yang_data
*frr_test_module_vrfs_vrf_interfaces_interface_get_elem(
109 struct nb_cb_get_elem_args
*args
)
111 const char *interface
;
113 interface
= listgetdata((struct listnode
*)args
->list_entry
);
114 return yang_data_new_string(args
->xpath
, interface
);
117 static const void *frr_test_module_vrfs_vrf_interfaces_interface_get_next(
118 struct nb_cb_get_next_args
*args
)
120 const struct tvrf
*vrf
;
121 struct listnode
*node
;
123 vrf
= listgetdata((struct listnode
*)args
->parent_list_entry
);
124 if (args
->list_entry
== NULL
)
125 node
= listhead(vrf
->interfaces
);
127 node
= listnextnode((struct listnode
*)args
->list_entry
);
133 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route
136 frr_test_module_vrfs_vrf_routes_route_get_next(struct nb_cb_get_next_args
*args
)
138 const struct tvrf
*vrf
;
139 struct listnode
*node
;
141 vrf
= listgetdata((struct listnode
*)args
->parent_list_entry
);
142 if (args
->list_entry
== NULL
)
143 node
= listhead(vrf
->routes
);
145 node
= listnextnode((struct listnode
*)args
->list_entry
);
151 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix
153 static struct yang_data
*frr_test_module_vrfs_vrf_routes_route_prefix_get_elem(
154 struct nb_cb_get_elem_args
*args
)
156 const struct troute
*route
;
158 route
= listgetdata((struct listnode
*)args
->list_entry
);
159 return yang_data_new_ipv4p(args
->xpath
, &route
->prefix
);
163 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop
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
)
169 const struct troute
*route
;
171 route
= listgetdata((struct listnode
*)args
->list_entry
);
172 return yang_data_new_ipv4(args
->xpath
, &route
->nexthop
);
176 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface
178 static struct yang_data
*
179 frr_test_module_vrfs_vrf_routes_route_interface_get_elem(
180 struct nb_cb_get_elem_args
*args
)
182 const struct troute
*route
;
184 route
= listgetdata((struct listnode
*)args
->list_entry
);
185 return yang_data_new_string(args
->xpath
, route
->ifname
);
189 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric
191 static struct yang_data
*frr_test_module_vrfs_vrf_routes_route_metric_get_elem(
192 struct nb_cb_get_elem_args
*args
)
194 const struct troute
*route
;
196 route
= listgetdata((struct listnode
*)args
->list_entry
);
197 return yang_data_new_uint8(args
->xpath
, route
->metric
);
201 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/active
203 static struct yang_data
*frr_test_module_vrfs_vrf_routes_route_active_get_elem(
204 struct nb_cb_get_elem_args
*args
)
206 const struct troute
*route
;
208 route
= listgetdata((struct listnode
*)args
->list_entry
);
210 return yang_data_new(args
->xpath
, NULL
);
215 /* clang-format off */
216 const struct frr_yang_module_info frr_test_module_info
= {
217 .name
= "frr-test-module",
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
,
226 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/name",
227 .cbs
.get_elem
= frr_test_module_vrfs_vrf_name_get_elem
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
263 /* clang-format on */
265 static const struct frr_yang_module_info
*const modules
[] = {
266 &frr_test_module_info
,
269 static void create_data(unsigned int num_vrfs
, unsigned int num_interfaces
,
270 unsigned int num_routes
)
272 struct prefix_ipv4 base_prefix
;
273 struct in_addr base_nexthop
;
275 (void)str2prefix_ipv4("10.0.0.0/32", &base_prefix
);
276 (void)inet_pton(AF_INET
, "172.16.0.0", &base_nexthop
);
281 for (unsigned int i
= 0; i
< num_vrfs
; i
++) {
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();
289 /* Create interfaces. */
290 for (unsigned int j
= 0; j
< num_interfaces
; j
++) {
294 snprintf(ifname
, sizeof(ifname
), "eth%u", j
);
295 interface
= XSTRDUP(MTYPE_TMP
, ifname
);
296 listnode_add(vrf
->interfaces
, interface
);
300 for (unsigned int j
= 0; j
< num_routes
; j
++) {
301 struct troute
*route
;
303 route
= XCALLOC(MTYPE_TMP
, sizeof(*route
));
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
);
310 memcpy(&route
->nexthop
, &base_nexthop
,
311 sizeof(route
->nexthop
));
312 route
->nexthop
.s_addr
=
313 htonl(ntohl(route
->nexthop
.s_addr
) + j
);
315 snprintf(route
->ifname
, sizeof(route
->ifname
), "eth%u",
317 route
->metric
= j
% 256;
318 route
->active
= (j
% 2 == 0);
319 listnode_add(vrf
->routes
, route
);
322 listnode_add(vrfs
, vrf
);
326 static void interface_delete(void *ptr
)
328 char *interface
= ptr
;
330 XFREE(MTYPE_TMP
, interface
);
333 static void route_delete(void *ptr
)
335 struct troute
*route
= ptr
;
337 XFREE(MTYPE_TMP
, route
);
340 static void vrf_delete(void *ptr
)
342 struct tvrf
*vrf
= ptr
;
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
);
351 static void delete_data(void)
353 vrfs
->del
= vrf_delete
;
357 static void vty_do_exit(int isexit
)
367 thread_master_free(master
);
369 log_memstats(stderr
, "test-nb-oper-data");
375 int main(int argc
, char **argv
)
377 struct thread thread
;
378 unsigned int num_vrfs
= 2;
379 unsigned int num_interfaces
= 4;
380 unsigned int num_routes
= 6;
383 num_vrfs
= atoi(argv
[1]);
385 num_interfaces
= atoi(argv
[2]);
387 num_routes
= atoi(argv
[3]);
389 /* Set umask before anything for security */
393 master
= thread_master_create(NULL
);
395 zlog_aux_init("NONE: ", ZLOG_DISABLED
);
399 cmd_hostname_set("test");
400 vty_init(master
, false);
403 nb_init(master
, modules
, array_size(modules
), false);
405 /* Create artificial data. */
406 create_data(num_vrfs
, num_interfaces
, num_routes
);
408 /* Read input from .in file. */
409 vty_stdio(vty_do_exit
);
411 /* Fetch next active thread. */
412 while (thread_fetch(master
, &thread
))
413 thread_call(&thread
);