1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2018 NetDEF, Inc.
15 #include "northbound.h"
17 static struct thread_master
*master
;
20 struct prefix_ipv4 prefix
;
21 struct in_addr nexthop
;
22 char ifname
[IFNAMSIZ
];
29 struct list
*interfaces
;
33 static struct list
*vrfs
;
36 * XPath: /frr-test-module:frr-test-module/vrfs/vrf
39 frr_test_module_vrfs_vrf_get_next(struct nb_cb_get_next_args
*args
)
41 struct listnode
*node
;
43 if (args
->list_entry
== NULL
)
44 node
= listhead(vrfs
);
46 node
= listnextnode((struct listnode
*)args
->list_entry
);
51 static int frr_test_module_vrfs_vrf_get_keys(struct nb_cb_get_keys_args
*args
)
53 const struct tvrf
*vrf
;
55 vrf
= listgetdata((struct listnode
*)args
->list_entry
);
58 strlcpy(args
->keys
->key
[0], vrf
->name
, sizeof(args
->keys
->key
[0]));
64 frr_test_module_vrfs_vrf_lookup_entry(struct nb_cb_lookup_entry_args
*args
)
66 struct listnode
*node
;
70 vrfname
= args
->keys
->key
[0];
72 for (ALL_LIST_ELEMENTS_RO(vrfs
, node
, vrf
)) {
73 if (strmatch(vrf
->name
, vrfname
))
81 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/name
83 static struct yang_data
*
84 frr_test_module_vrfs_vrf_name_get_elem(struct nb_cb_get_elem_args
*args
)
86 const struct tvrf
*vrf
;
88 vrf
= listgetdata((struct listnode
*)args
->list_entry
);
89 return yang_data_new_string(args
->xpath
, vrf
->name
);
93 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/interfaces/interface
95 static struct yang_data
*frr_test_module_vrfs_vrf_interfaces_interface_get_elem(
96 struct nb_cb_get_elem_args
*args
)
98 const char *interface
;
100 interface
= listgetdata((struct listnode
*)args
->list_entry
);
101 return yang_data_new_string(args
->xpath
, interface
);
104 static const void *frr_test_module_vrfs_vrf_interfaces_interface_get_next(
105 struct nb_cb_get_next_args
*args
)
107 const struct tvrf
*vrf
;
108 struct listnode
*node
;
110 vrf
= listgetdata((struct listnode
*)args
->parent_list_entry
);
111 if (args
->list_entry
== NULL
)
112 node
= listhead(vrf
->interfaces
);
114 node
= listnextnode((struct listnode
*)args
->list_entry
);
120 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route
123 frr_test_module_vrfs_vrf_routes_route_get_next(struct nb_cb_get_next_args
*args
)
125 const struct tvrf
*vrf
;
126 struct listnode
*node
;
128 vrf
= listgetdata((struct listnode
*)args
->parent_list_entry
);
129 if (args
->list_entry
== NULL
)
130 node
= listhead(vrf
->routes
);
132 node
= listnextnode((struct listnode
*)args
->list_entry
);
138 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix
140 static struct yang_data
*frr_test_module_vrfs_vrf_routes_route_prefix_get_elem(
141 struct nb_cb_get_elem_args
*args
)
143 const struct troute
*route
;
145 route
= listgetdata((struct listnode
*)args
->list_entry
);
146 return yang_data_new_ipv4p(args
->xpath
, &route
->prefix
);
150 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop
152 static struct yang_data
*
153 frr_test_module_vrfs_vrf_routes_route_next_hop_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_ipv4(args
->xpath
, &route
->nexthop
);
163 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface
165 static struct yang_data
*
166 frr_test_module_vrfs_vrf_routes_route_interface_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_string(args
->xpath
, route
->ifname
);
176 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric
178 static struct yang_data
*frr_test_module_vrfs_vrf_routes_route_metric_get_elem(
179 struct nb_cb_get_elem_args
*args
)
181 const struct troute
*route
;
183 route
= listgetdata((struct listnode
*)args
->list_entry
);
184 return yang_data_new_uint8(args
->xpath
, route
->metric
);
188 * XPath: /frr-test-module:frr-test-module/vrfs/vrf/routes/route/active
190 static struct yang_data
*frr_test_module_vrfs_vrf_routes_route_active_get_elem(
191 struct nb_cb_get_elem_args
*args
)
193 const struct troute
*route
;
195 route
= listgetdata((struct listnode
*)args
->list_entry
);
197 return yang_data_new(args
->xpath
, NULL
);
202 /* clang-format off */
203 const struct frr_yang_module_info frr_test_module_info
= {
204 .name
= "frr-test-module",
207 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf",
208 .cbs
.get_next
= frr_test_module_vrfs_vrf_get_next
,
209 .cbs
.get_keys
= frr_test_module_vrfs_vrf_get_keys
,
210 .cbs
.lookup_entry
= frr_test_module_vrfs_vrf_lookup_entry
,
213 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/name",
214 .cbs
.get_elem
= frr_test_module_vrfs_vrf_name_get_elem
,
217 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/interfaces/interface",
218 .cbs
.get_elem
= frr_test_module_vrfs_vrf_interfaces_interface_get_elem
,
219 .cbs
.get_next
= frr_test_module_vrfs_vrf_interfaces_interface_get_next
,
222 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route",
223 .cbs
.get_next
= frr_test_module_vrfs_vrf_routes_route_get_next
,
226 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/prefix",
227 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_prefix_get_elem
,
230 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/next-hop",
231 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_next_hop_get_elem
,
234 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/interface",
235 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_interface_get_elem
,
238 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/metric",
239 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_metric_get_elem
,
242 .xpath
= "/frr-test-module:frr-test-module/vrfs/vrf/routes/route/active",
243 .cbs
.get_elem
= frr_test_module_vrfs_vrf_routes_route_active_get_elem
,
250 /* clang-format on */
252 static const struct frr_yang_module_info
*const modules
[] = {
253 &frr_test_module_info
,
256 static void create_data(unsigned int num_vrfs
, unsigned int num_interfaces
,
257 unsigned int num_routes
)
259 struct prefix_ipv4 base_prefix
;
260 struct in_addr base_nexthop
;
262 (void)str2prefix_ipv4("10.0.0.0/32", &base_prefix
);
263 (void)inet_pton(AF_INET
, "172.16.0.0", &base_nexthop
);
268 for (unsigned int i
= 0; i
< num_vrfs
; i
++) {
271 vrf
= XCALLOC(MTYPE_TMP
, sizeof(*vrf
));
272 snprintf(vrf
->name
, sizeof(vrf
->name
), "vrf%u", i
);
273 vrf
->interfaces
= list_new();
274 vrf
->routes
= list_new();
276 /* Create interfaces. */
277 for (unsigned int j
= 0; j
< num_interfaces
; j
++) {
281 snprintf(ifname
, sizeof(ifname
), "eth%u", j
);
282 interface
= XSTRDUP(MTYPE_TMP
, ifname
);
283 listnode_add(vrf
->interfaces
, interface
);
287 for (unsigned int j
= 0; j
< num_routes
; j
++) {
288 struct troute
*route
;
290 route
= XCALLOC(MTYPE_TMP
, sizeof(*route
));
292 memcpy(&route
->prefix
, &base_prefix
,
293 sizeof(route
->prefix
));
294 route
->prefix
.prefix
.s_addr
=
295 htonl(ntohl(route
->prefix
.prefix
.s_addr
) + j
);
297 memcpy(&route
->nexthop
, &base_nexthop
,
298 sizeof(route
->nexthop
));
299 route
->nexthop
.s_addr
=
300 htonl(ntohl(route
->nexthop
.s_addr
) + j
);
302 snprintf(route
->ifname
, sizeof(route
->ifname
), "eth%u",
304 route
->metric
= j
% 256;
305 route
->active
= (j
% 2 == 0);
306 listnode_add(vrf
->routes
, route
);
309 listnode_add(vrfs
, vrf
);
313 static void interface_delete(void *ptr
)
315 char *interface
= ptr
;
317 XFREE(MTYPE_TMP
, interface
);
320 static void route_delete(void *ptr
)
322 struct troute
*route
= ptr
;
324 XFREE(MTYPE_TMP
, route
);
327 static void vrf_delete(void *ptr
)
329 struct tvrf
*vrf
= ptr
;
331 vrf
->interfaces
->del
= interface_delete
;
332 list_delete(&vrf
->interfaces
);
333 vrf
->routes
->del
= route_delete
;
334 list_delete(&vrf
->routes
);
335 XFREE(MTYPE_TMP
, vrf
);
338 static void delete_data(void)
340 vrfs
->del
= vrf_delete
;
344 static void vty_do_exit(int isexit
)
354 thread_master_free(master
);
356 log_memstats(stderr
, "test-nb-oper-data");
362 int main(int argc
, char **argv
)
364 struct thread thread
;
365 unsigned int num_vrfs
= 2;
366 unsigned int num_interfaces
= 4;
367 unsigned int num_routes
= 6;
370 num_vrfs
= atoi(argv
[1]);
372 num_interfaces
= atoi(argv
[2]);
374 num_routes
= atoi(argv
[3]);
376 /* Set umask before anything for security */
380 master
= thread_master_create(NULL
);
382 zlog_aux_init("NONE: ", ZLOG_DISABLED
);
386 cmd_hostname_set("test");
387 vty_init(master
, false);
389 nb_init(master
, modules
, array_size(modules
), false);
391 /* Create artificial data. */
392 create_data(num_vrfs
, num_interfaces
, num_routes
);
394 /* Read input from .in file. */
395 vty_stdio(vty_do_exit
);
397 /* Fetch next active thread. */
398 while (thread_fetch(master
, &thread
))
399 thread_call(&thread
);