]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_northbound.c
Merge remote-tracking branch 'frr/master' into rip-vrf
[mirror_frr.git] / ripngd / ripng_northbound.c
CommitLineData
e9ce224b
RW
1/*
2 * Copyright (C) 1998 Kunihiro Ishiguro
3 * Copyright (C) 2018 NetDEF, Inc.
4 * Renato Westphal
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <zebra.h>
22
23#include "if.h"
24#include "vrf.h"
25#include "log.h"
26#include "prefix.h"
27#include "table.h"
28#include "command.h"
29#include "routemap.h"
49e06d25 30#include "agg_table.h"
e9ce224b
RW
31#include "northbound.h"
32#include "libfrr.h"
33
34#include "ripngd/ripngd.h"
c5b2b5f6 35#include "ripngd/ripng_debug.h"
6fc29385 36#include "ripngd/ripng_route.h"
e9ce224b
RW
37#include "ripngd/ripng_cli.h"
38
39/*
40 * XPath: /frr-ripngd:ripngd/instance
41 */
42static int ripngd_instance_create(enum nb_event event,
43 const struct lyd_node *dnode,
44 union nb_resource *resource)
45{
5c84b9a5
RW
46 struct ripng *ripng;
47 struct vrf *vrf;
dde7b15b 48 const char *vrf_name;
9a12e9e5
RW
49 int socket;
50
dde7b15b
RW
51 vrf_name = yang_dnode_get_string(dnode, "./vrf");
52 vrf = vrf_lookup_by_name(vrf_name);
53
54 /*
55 * Try to create a RIPng socket only if the VRF is enabled, otherwise
56 * create a disabled RIPng instance and wait for the VRF to be enabled.
57 */
9a12e9e5
RW
58 switch (event) {
59 case NB_EV_VALIDATE:
60 break;
61 case NB_EV_PREPARE:
dde7b15b
RW
62 if (!vrf || !vrf_is_enabled(vrf))
63 break;
64
65 socket = ripng_make_socket(vrf);
9a12e9e5
RW
66 if (socket < 0)
67 return NB_ERR_RESOURCE;
68 resource->fd = socket;
69 break;
70 case NB_EV_ABORT:
dde7b15b
RW
71 if (!vrf || !vrf_is_enabled(vrf))
72 break;
73
9a12e9e5
RW
74 socket = resource->fd;
75 close(socket);
76 break;
77 case NB_EV_APPLY:
dde7b15b
RW
78 if (vrf && vrf_is_enabled(vrf))
79 socket = resource->fd;
80 else
81 socket = -1;
82
83 ripng = ripng_create(vrf_name, vrf, socket);
5c84b9a5 84 yang_dnode_set_entry(dnode, ripng);
9a12e9e5
RW
85 break;
86 }
87
e9ce224b
RW
88 return NB_OK;
89}
90
91static int ripngd_instance_delete(enum nb_event event,
92 const struct lyd_node *dnode)
93{
5c84b9a5
RW
94 struct ripng *ripng;
95
9a12e9e5
RW
96 if (event != NB_EV_APPLY)
97 return NB_OK;
98
5c84b9a5
RW
99 ripng = yang_dnode_get_entry(dnode, true);
100 ripng_clean(ripng);
9a12e9e5 101
e9ce224b
RW
102 return NB_OK;
103}
104
80cf4e45
RW
105static const void *ripngd_instance_get_next(const void *parent_list_entry,
106 const void *list_entry)
107{
108 const struct ripng *ripng = list_entry;
109
110 if (list_entry == NULL)
111 ripng = RB_MIN(ripng_instance_head, &ripng_instances);
112 else
113 ripng = RB_NEXT(ripng_instance_head, (struct ripng *)ripng);
114
115 return ripng;
116}
117
118static int ripngd_instance_get_keys(const void *list_entry,
119 struct yang_list_keys *keys)
120{
121 const struct ripng *ripng = list_entry;
122
123 keys->num = 1;
124 strlcpy(keys->key[0], ripng->vrf_name, sizeof(keys->key[0]));
125
126 return NB_OK;
127}
128
129static const void *
130ripngd_instance_lookup_entry(const void *parent_list_entry,
131 const struct yang_list_keys *keys)
132{
133 const char *vrf_name = keys->key[0];
134
135 return ripng_lookup_by_vrf_name(vrf_name);
136}
137
e9ce224b
RW
138/*
139 * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
140 */
141static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
142 const struct lyd_node *dnode,
143 union nb_resource *resource)
144{
5c84b9a5
RW
145 struct ripng *ripng;
146
1e42a07c
RW
147 if (event != NB_EV_APPLY)
148 return NB_OK;
149
5c84b9a5 150 ripng = yang_dnode_get_entry(dnode, true);
1e42a07c
RW
151 ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
152 if (!ripng->ecmp)
5c84b9a5 153 ripng_ecmp_disable(ripng);
1e42a07c 154
e9ce224b
RW
155 return NB_OK;
156}
157
158/*
159 * XPath: /frr-ripngd:ripngd/instance/default-information-originate
160 */
161static int ripngd_instance_default_information_originate_modify(
162 enum nb_event event, const struct lyd_node *dnode,
163 union nb_resource *resource)
164{
5c84b9a5 165 struct ripng *ripng;
54b56562
RW
166 bool default_information;
167 struct prefix_ipv6 p;
168
169 if (event != NB_EV_APPLY)
170 return NB_OK;
171
5c84b9a5 172 ripng = yang_dnode_get_entry(dnode, true);
54b56562 173 default_information = yang_dnode_get_bool(dnode, NULL);
5c84b9a5 174
54b56562
RW
175 str2prefix_ipv6("::/0", &p);
176 if (default_information) {
5c84b9a5
RW
177 ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
178 RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
54b56562 179 } else {
5c84b9a5 180 ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
54b56562
RW
181 RIPNG_ROUTE_DEFAULT, &p, 0);
182 }
183
e9ce224b
RW
184 return NB_OK;
185}
186
187/*
188 * XPath: /frr-ripngd:ripngd/instance/default-metric
189 */
190static int ripngd_instance_default_metric_modify(enum nb_event event,
191 const struct lyd_node *dnode,
192 union nb_resource *resource)
193{
5c84b9a5
RW
194 struct ripng *ripng;
195
ad8778c0
RW
196 if (event != NB_EV_APPLY)
197 return NB_OK;
198
5c84b9a5 199 ripng = yang_dnode_get_entry(dnode, true);
ad8778c0
RW
200 ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
201
e9ce224b
RW
202 return NB_OK;
203}
204
205/*
206 * XPath: /frr-ripngd:ripngd/instance/network
207 */
208static int ripngd_instance_network_create(enum nb_event event,
209 const struct lyd_node *dnode,
210 union nb_resource *resource)
211{
5c84b9a5 212 struct ripng *ripng;
cc48702b
RW
213 struct prefix p;
214
215 if (event != NB_EV_APPLY)
216 return NB_OK;
217
5c84b9a5 218 ripng = yang_dnode_get_entry(dnode, true);
cc48702b
RW
219 yang_dnode_get_ipv6p(&p, dnode, NULL);
220 apply_mask_ipv6((struct prefix_ipv6 *)&p);
221
5c84b9a5 222 return ripng_enable_network_add(ripng, &p);
e9ce224b
RW
223}
224
225static int ripngd_instance_network_delete(enum nb_event event,
226 const struct lyd_node *dnode)
227{
5c84b9a5 228 struct ripng *ripng;
cc48702b
RW
229 struct prefix p;
230
231 if (event != NB_EV_APPLY)
232 return NB_OK;
233
5c84b9a5 234 ripng = yang_dnode_get_entry(dnode, true);
cc48702b
RW
235 yang_dnode_get_ipv6p(&p, dnode, NULL);
236 apply_mask_ipv6((struct prefix_ipv6 *)&p);
237
5c84b9a5 238 return ripng_enable_network_delete(ripng, &p);
e9ce224b
RW
239}
240
241/*
242 * XPath: /frr-ripngd:ripngd/instance/interface
243 */
244static int ripngd_instance_interface_create(enum nb_event event,
245 const struct lyd_node *dnode,
246 union nb_resource *resource)
247{
5c84b9a5 248 struct ripng *ripng;
cc48702b
RW
249 const char *ifname;
250
251 if (event != NB_EV_APPLY)
252 return NB_OK;
253
5c84b9a5 254 ripng = yang_dnode_get_entry(dnode, true);
cc48702b
RW
255 ifname = yang_dnode_get_string(dnode, NULL);
256
5c84b9a5 257 return ripng_enable_if_add(ripng, ifname);
e9ce224b
RW
258}
259
260static int ripngd_instance_interface_delete(enum nb_event event,
261 const struct lyd_node *dnode)
262{
5c84b9a5 263 struct ripng *ripng;
cc48702b
RW
264 const char *ifname;
265
266 if (event != NB_EV_APPLY)
267 return NB_OK;
268
5c84b9a5 269 ripng = yang_dnode_get_entry(dnode, true);
cc48702b
RW
270 ifname = yang_dnode_get_string(dnode, NULL);
271
5c84b9a5 272 return ripng_enable_if_delete(ripng, ifname);
e9ce224b
RW
273}
274
275/*
276 * XPath: /frr-ripngd:ripngd/instance/offset-list
277 */
278static int ripngd_instance_offset_list_create(enum nb_event event,
279 const struct lyd_node *dnode,
280 union nb_resource *resource)
281{
5c84b9a5 282 struct ripng *ripng;
b09956ca
RW
283 const char *ifname;
284 struct ripng_offset_list *offset;
285
286 if (event != NB_EV_APPLY)
287 return NB_OK;
288
5c84b9a5 289 ripng = yang_dnode_get_entry(dnode, true);
b09956ca
RW
290 ifname = yang_dnode_get_string(dnode, "./interface");
291
5c84b9a5 292 offset = ripng_offset_list_new(ripng, ifname);
b09956ca
RW
293 yang_dnode_set_entry(dnode, offset);
294
e9ce224b
RW
295 return NB_OK;
296}
297
298static int ripngd_instance_offset_list_delete(enum nb_event event,
299 const struct lyd_node *dnode)
300{
b09956ca
RW
301 int direct;
302 struct ripng_offset_list *offset;
303
304 if (event != NB_EV_APPLY)
305 return NB_OK;
306
307 direct = yang_dnode_get_enum(dnode, "./direction");
308
309 offset = yang_dnode_get_entry(dnode, true);
310 if (offset->direct[direct].alist_name) {
311 free(offset->direct[direct].alist_name);
312 offset->direct[direct].alist_name = NULL;
313 }
314 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
315 && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
316 ripng_offset_list_del(offset);
317
e9ce224b
RW
318 return NB_OK;
319}
320
321/*
322 * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
323 */
324static int
325ripngd_instance_offset_list_access_list_modify(enum nb_event event,
326 const struct lyd_node *dnode,
327 union nb_resource *resource)
328{
b09956ca
RW
329 int direct;
330 struct ripng_offset_list *offset;
331 const char *alist_name;
332
333 if (event != NB_EV_APPLY)
334 return NB_OK;
335
336 direct = yang_dnode_get_enum(dnode, "../direction");
337 alist_name = yang_dnode_get_string(dnode, NULL);
338
339 offset = yang_dnode_get_entry(dnode, true);
340 if (offset->direct[direct].alist_name)
341 free(offset->direct[direct].alist_name);
342 offset->direct[direct].alist_name = strdup(alist_name);
343
e9ce224b
RW
344 return NB_OK;
345}
346
347/*
348 * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
349 */
350static int
351ripngd_instance_offset_list_metric_modify(enum nb_event event,
352 const struct lyd_node *dnode,
353 union nb_resource *resource)
354{
b09956ca
RW
355 int direct;
356 uint8_t metric;
357 struct ripng_offset_list *offset;
358
359 if (event != NB_EV_APPLY)
360 return NB_OK;
361
362 direct = yang_dnode_get_enum(dnode, "../direction");
363 metric = yang_dnode_get_uint8(dnode, NULL);
364
365 offset = yang_dnode_get_entry(dnode, true);
366 offset->direct[direct].metric = metric;
367
e9ce224b
RW
368 return NB_OK;
369}
370
371/*
372 * XPath: /frr-ripngd:ripngd/instance/passive-interface
373 */
374static int
375ripngd_instance_passive_interface_create(enum nb_event event,
376 const struct lyd_node *dnode,
377 union nb_resource *resource)
378{
5c84b9a5 379 struct ripng *ripng;
22e8c7ae
RW
380 const char *ifname;
381
382 if (event != NB_EV_APPLY)
383 return NB_OK;
384
5c84b9a5 385 ripng = yang_dnode_get_entry(dnode, true);
22e8c7ae
RW
386 ifname = yang_dnode_get_string(dnode, NULL);
387
5c84b9a5 388 return ripng_passive_interface_set(ripng, ifname);
e9ce224b
RW
389}
390
391static int
392ripngd_instance_passive_interface_delete(enum nb_event event,
393 const struct lyd_node *dnode)
394{
5c84b9a5 395 struct ripng *ripng;
22e8c7ae
RW
396 const char *ifname;
397
398 if (event != NB_EV_APPLY)
399 return NB_OK;
400
5c84b9a5 401 ripng = yang_dnode_get_entry(dnode, true);
22e8c7ae
RW
402 ifname = yang_dnode_get_string(dnode, NULL);
403
5c84b9a5 404 return ripng_passive_interface_unset(ripng, ifname);
e9ce224b
RW
405}
406
407/*
408 * XPath: /frr-ripngd:ripngd/instance/redistribute
409 */
410static int ripngd_instance_redistribute_create(enum nb_event event,
411 const struct lyd_node *dnode,
412 union nb_resource *resource)
413{
f9120f71
RW
414 struct ripng *ripng;
415 int type;
416
417 if (event != NB_EV_APPLY)
418 return NB_OK;
419
420 ripng = yang_dnode_get_entry(dnode, true);
421 type = yang_dnode_get_enum(dnode, "./protocol");
422
423 ripng->redist[type].enabled = true;
424
e9ce224b
RW
425 return NB_OK;
426}
427
428static int ripngd_instance_redistribute_delete(enum nb_event event,
429 const struct lyd_node *dnode)
430{
5c84b9a5 431 struct ripng *ripng;
db2038c7
RW
432 int type;
433
434 if (event != NB_EV_APPLY)
435 return NB_OK;
436
5c84b9a5 437 ripng = yang_dnode_get_entry(dnode, true);
db2038c7
RW
438 type = yang_dnode_get_enum(dnode, "./protocol");
439
f9120f71
RW
440 ripng->redist[type].enabled = false;
441 if (ripng->redist[type].route_map.name) {
442 free(ripng->redist[type].route_map.name);
443 ripng->redist[type].route_map.name = NULL;
444 ripng->redist[type].route_map.map = NULL;
445 }
446 ripng->redist[type].metric_config = false;
447 ripng->redist[type].metric = 0;
448
449 if (ripng->enabled)
450 ripng_redistribute_conf_delete(ripng, type);
db2038c7 451
e9ce224b
RW
452 return NB_OK;
453}
454
db2038c7
RW
455static void
456ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
457{
5c84b9a5 458 struct ripng *ripng;
db2038c7
RW
459 int type;
460
5c84b9a5 461 ripng = yang_dnode_get_entry(dnode, true);
db2038c7 462 type = yang_dnode_get_enum(dnode, "./protocol");
5c84b9a5 463
f9120f71
RW
464 if (ripng->enabled)
465 ripng_redistribute_conf_update(ripng, type);
db2038c7
RW
466}
467
e9ce224b
RW
468/*
469 * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
470 */
471static int
472ripngd_instance_redistribute_route_map_modify(enum nb_event event,
473 const struct lyd_node *dnode,
474 union nb_resource *resource)
475{
5c84b9a5 476 struct ripng *ripng;
db2038c7
RW
477 int type;
478 const char *rmap_name;
479
480 if (event != NB_EV_APPLY)
481 return NB_OK;
482
5c84b9a5 483 ripng = yang_dnode_get_entry(dnode, true);
db2038c7
RW
484 type = yang_dnode_get_enum(dnode, "../protocol");
485 rmap_name = yang_dnode_get_string(dnode, NULL);
486
f9120f71
RW
487 if (ripng->redist[type].route_map.name)
488 free(ripng->redist[type].route_map.name);
489 ripng->redist[type].route_map.name = strdup(rmap_name);
490 ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
db2038c7 491
e9ce224b
RW
492 return NB_OK;
493}
494
495static int
496ripngd_instance_redistribute_route_map_delete(enum nb_event event,
497 const struct lyd_node *dnode)
498{
5c84b9a5 499 struct ripng *ripng;
db2038c7
RW
500 int type;
501
502 if (event != NB_EV_APPLY)
503 return NB_OK;
504
5c84b9a5 505 ripng = yang_dnode_get_entry(dnode, true);
db2038c7
RW
506 type = yang_dnode_get_enum(dnode, "../protocol");
507
f9120f71
RW
508 free(ripng->redist[type].route_map.name);
509 ripng->redist[type].route_map.name = NULL;
510 ripng->redist[type].route_map.map = NULL;
db2038c7 511
e9ce224b
RW
512 return NB_OK;
513}
514
515/*
516 * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
517 */
518static int
519ripngd_instance_redistribute_metric_modify(enum nb_event event,
520 const struct lyd_node *dnode,
521 union nb_resource *resource)
522{
5c84b9a5 523 struct ripng *ripng;
db2038c7
RW
524 int type;
525 uint8_t metric;
526
527 if (event != NB_EV_APPLY)
528 return NB_OK;
529
5c84b9a5 530 ripng = yang_dnode_get_entry(dnode, true);
db2038c7
RW
531 type = yang_dnode_get_enum(dnode, "../protocol");
532 metric = yang_dnode_get_uint8(dnode, NULL);
533
f9120f71
RW
534 ripng->redist[type].metric_config = true;
535 ripng->redist[type].metric = metric;
db2038c7 536
e9ce224b
RW
537 return NB_OK;
538}
539
540static int
541ripngd_instance_redistribute_metric_delete(enum nb_event event,
542 const struct lyd_node *dnode)
543{
5c84b9a5 544 struct ripng *ripng;
db2038c7
RW
545 int type;
546
547 if (event != NB_EV_APPLY)
548 return NB_OK;
549
5c84b9a5 550 ripng = yang_dnode_get_entry(dnode, true);
db2038c7
RW
551 type = yang_dnode_get_enum(dnode, "../protocol");
552
f9120f71
RW
553 ripng->redist[type].metric_config = false;
554 ripng->redist[type].metric = 0;
db2038c7 555
e9ce224b
RW
556 return NB_OK;
557}
558
559/*
560 * XPath: /frr-ripngd:ripngd/instance/static-route
561 */
562static int ripngd_instance_static_route_create(enum nb_event event,
563 const struct lyd_node *dnode,
564 union nb_resource *resource)
565{
5c84b9a5 566 struct ripng *ripng;
521d1b12
RW
567 struct prefix_ipv6 p;
568
569 if (event != NB_EV_APPLY)
570 return NB_OK;
571
5c84b9a5 572 ripng = yang_dnode_get_entry(dnode, true);
521d1b12
RW
573 yang_dnode_get_ipv6p(&p, dnode, NULL);
574 apply_mask_ipv6(&p);
575
5c84b9a5
RW
576 ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
577 0, NULL, 0);
521d1b12 578
e9ce224b
RW
579 return NB_OK;
580}
581
582static int ripngd_instance_static_route_delete(enum nb_event event,
583 const struct lyd_node *dnode)
584{
5c84b9a5 585 struct ripng *ripng;
521d1b12
RW
586 struct prefix_ipv6 p;
587
588 if (event != NB_EV_APPLY)
589 return NB_OK;
590
5c84b9a5 591 ripng = yang_dnode_get_entry(dnode, true);
521d1b12
RW
592 yang_dnode_get_ipv6p(&p, dnode, NULL);
593 apply_mask_ipv6(&p);
594
5c84b9a5
RW
595 ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
596 &p, 0);
521d1b12 597
e9ce224b
RW
598 return NB_OK;
599}
600
601/*
602 * XPath: /frr-ripngd:ripngd/instance/aggregate-address
603 */
604static int
605ripngd_instance_aggregate_address_create(enum nb_event event,
606 const struct lyd_node *dnode,
607 union nb_resource *resource)
608{
5c84b9a5 609 struct ripng *ripng;
6fc29385
RW
610 struct prefix_ipv6 p;
611
612 if (event != NB_EV_APPLY)
613 return NB_OK;
614
5c84b9a5 615 ripng = yang_dnode_get_entry(dnode, true);
6fc29385
RW
616 yang_dnode_get_ipv6p(&p, dnode, NULL);
617 apply_mask_ipv6(&p);
618
5c84b9a5 619 ripng_aggregate_add(ripng, (struct prefix *)&p);
6fc29385 620
e9ce224b
RW
621 return NB_OK;
622}
623
624static int
625ripngd_instance_aggregate_address_delete(enum nb_event event,
626 const struct lyd_node *dnode)
627{
5c84b9a5 628 struct ripng *ripng;
6fc29385
RW
629 struct prefix_ipv6 p;
630
631 if (event != NB_EV_APPLY)
632 return NB_OK;
633
5c84b9a5 634 ripng = yang_dnode_get_entry(dnode, true);
6fc29385
RW
635 yang_dnode_get_ipv6p(&p, dnode, NULL);
636 apply_mask_ipv6(&p);
637
5c84b9a5 638 ripng_aggregate_delete(ripng, (struct prefix *)&p);
6fc29385 639
e9ce224b
RW
640 return NB_OK;
641}
642
f8981ec5
RW
643/*
644 * XPath: /frr-ripngd:ripngd/instance/timers
645 */
646static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
647{
5c84b9a5
RW
648 struct ripng *ripng;
649
650 ripng = yang_dnode_get_entry(dnode, true);
651
f8981ec5 652 /* Reset update timer thread. */
5c84b9a5 653 ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
f8981ec5
RW
654}
655
e9ce224b
RW
656/*
657 * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
658 */
659static int
660ripngd_instance_timers_flush_interval_modify(enum nb_event event,
661 const struct lyd_node *dnode,
662 union nb_resource *resource)
663{
5c84b9a5
RW
664 struct ripng *ripng;
665
f8981ec5
RW
666 if (event != NB_EV_APPLY)
667 return NB_OK;
668
5c84b9a5 669 ripng = yang_dnode_get_entry(dnode, true);
f8981ec5
RW
670 ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
671
e9ce224b
RW
672 return NB_OK;
673}
674
675/*
676 * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
677 */
678static int
679ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
680 const struct lyd_node *dnode,
681 union nb_resource *resource)
682{
5c84b9a5
RW
683 struct ripng *ripng;
684
f8981ec5
RW
685 if (event != NB_EV_APPLY)
686 return NB_OK;
687
5c84b9a5 688 ripng = yang_dnode_get_entry(dnode, true);
f8981ec5
RW
689 ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
690
e9ce224b
RW
691 return NB_OK;
692}
693
694/*
695 * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
696 */
697static int
698ripngd_instance_timers_update_interval_modify(enum nb_event event,
699 const struct lyd_node *dnode,
700 union nb_resource *resource)
701{
5c84b9a5
RW
702 struct ripng *ripng;
703
f8981ec5
RW
704 if (event != NB_EV_APPLY)
705 return NB_OK;
706
5c84b9a5 707 ripng = yang_dnode_get_entry(dnode, true);
f8981ec5
RW
708 ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
709
e9ce224b
RW
710 return NB_OK;
711}
712
713/*
80cf4e45 714 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor
e9ce224b
RW
715 */
716static const void *
80cf4e45
RW
717ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
718 const void *list_entry)
e9ce224b 719{
80cf4e45 720 const struct ripng *ripng = parent_list_entry;
a8bf8fb8
RW
721 struct listnode *node;
722
723 if (list_entry == NULL)
ecece94c 724 node = listhead(ripng->peer_list);
a8bf8fb8
RW
725 else
726 node = listnextnode((struct listnode *)list_entry);
727
728 return node;
e9ce224b
RW
729}
730
80cf4e45
RW
731static int
732ripngd_instance_state_neighbors_neighbor_get_keys(const void *list_entry,
733 struct yang_list_keys *keys)
e9ce224b 734{
a8bf8fb8
RW
735 const struct listnode *node = list_entry;
736 const struct ripng_peer *peer = listgetdata(node);
737
738 keys->num = 1;
739 (void)inet_ntop(AF_INET6, &peer->addr, keys->key[0],
740 sizeof(keys->key[0]));
741
e9ce224b
RW
742 return NB_OK;
743}
744
80cf4e45
RW
745static const void *ripngd_instance_state_neighbors_neighbor_lookup_entry(
746 const void *parent_list_entry, const struct yang_list_keys *keys)
e9ce224b 747{
80cf4e45 748 const struct ripng *ripng = parent_list_entry;
a8bf8fb8
RW
749 struct in6_addr address;
750 struct ripng_peer *peer;
751 struct listnode *node;
752
753 yang_str2ipv6(keys->key[0], &address);
754
ecece94c 755 for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) {
a8bf8fb8
RW
756 if (IPV6_ADDR_SAME(&peer->addr, &address))
757 return node;
758 }
759
e9ce224b
RW
760 return NULL;
761}
762
763/*
80cf4e45 764 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address
e9ce224b
RW
765 */
766static struct yang_data *
80cf4e45
RW
767ripngd_instance_state_neighbors_neighbor_address_get_elem(
768 const char *xpath, const void *list_entry)
e9ce224b 769{
a8bf8fb8
RW
770 const struct listnode *node = list_entry;
771 const struct ripng_peer *peer = listgetdata(node);
772
773 return yang_data_new_ipv6(xpath, &peer->addr);
e9ce224b
RW
774}
775
776/*
80cf4e45 777 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update
e9ce224b
RW
778 */
779static struct yang_data *
80cf4e45
RW
780ripngd_instance_state_neighbors_neighbor_last_update_get_elem(
781 const char *xpath, const void *list_entry)
e9ce224b 782{
a8bf8fb8 783 /* TODO: yang:date-and-time is tricky */
e9ce224b
RW
784 return NULL;
785}
786
787/*
80cf4e45 788 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd
e9ce224b
RW
789 */
790static struct yang_data *
80cf4e45 791ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
e9ce224b
RW
792 const char *xpath, const void *list_entry)
793{
a8bf8fb8
RW
794 const struct listnode *node = list_entry;
795 const struct ripng_peer *peer = listgetdata(node);
796
797 return yang_data_new_uint32(xpath, peer->recv_badpackets);
e9ce224b
RW
798}
799
800/*
80cf4e45 801 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd
e9ce224b
RW
802 */
803static struct yang_data *
80cf4e45
RW
804ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
805 const char *xpath, const void *list_entry)
e9ce224b 806{
a8bf8fb8
RW
807 const struct listnode *node = list_entry;
808 const struct ripng_peer *peer = listgetdata(node);
809
810 return yang_data_new_uint32(xpath, peer->recv_badroutes);
e9ce224b
RW
811}
812
813/*
80cf4e45 814 * XPath: /frr-ripngd:ripngd/instance/state/routes/route
e9ce224b
RW
815 */
816static const void *
80cf4e45
RW
817ripngd_instance_state_routes_route_get_next(const void *parent_list_entry,
818 const void *list_entry)
e9ce224b 819{
80cf4e45 820 const struct ripng *ripng = parent_list_entry;
5707da09
RW
821 struct agg_node *rn;
822
5707da09
RW
823 if (list_entry == NULL)
824 rn = agg_route_top(ripng->table);
825 else
826 rn = agg_route_next((struct agg_node *)list_entry);
827 while (rn && rn->info == NULL)
828 rn = agg_route_next(rn);
829
830 return rn;
e9ce224b
RW
831}
832
80cf4e45
RW
833static int
834ripngd_instance_state_routes_route_get_keys(const void *list_entry,
835 struct yang_list_keys *keys)
e9ce224b 836{
5707da09
RW
837 const struct agg_node *rn = list_entry;
838
839 keys->num = 1;
840 (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0]));
841
e9ce224b
RW
842 return NB_OK;
843}
844
80cf4e45
RW
845static const void *ripngd_instance_state_routes_route_lookup_entry(
846 const void *parent_list_entry, const struct yang_list_keys *keys)
e9ce224b 847{
80cf4e45 848 const struct ripng *ripng = parent_list_entry;
5707da09
RW
849 struct prefix prefix;
850 struct agg_node *rn;
851
852 yang_str2ipv6p(keys->key[0], &prefix);
853
854 rn = agg_node_lookup(ripng->table, &prefix);
855 if (!rn || !rn->info)
856 return NULL;
857
858 agg_unlock_node(rn);
859
860 return rn;
e9ce224b
RW
861}
862
863/*
80cf4e45 864 * XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix
e9ce224b
RW
865 */
866static struct yang_data *
80cf4e45
RW
867ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath,
868 const void *list_entry)
e9ce224b 869{
5707da09
RW
870 const struct agg_node *rn = list_entry;
871 const struct ripng_info *rinfo = listnode_head(rn->info);
872
873 return yang_data_new_ipv6p(xpath, &rinfo->rp->p);
e9ce224b
RW
874}
875
876/*
80cf4e45 877 * XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop
e9ce224b
RW
878 */
879static struct yang_data *
80cf4e45
RW
880ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
881 const void *list_entry)
e9ce224b 882{
5707da09
RW
883 const struct agg_node *rn = list_entry;
884 const struct ripng_info *rinfo = listnode_head(rn->info);
885
886 return yang_data_new_ipv6(xpath, &rinfo->nexthop);
e9ce224b
RW
887}
888
889/*
80cf4e45 890 * XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface
e9ce224b
RW
891 */
892static struct yang_data *
80cf4e45
RW
893ripngd_instance_state_routes_route_interface_get_elem(const char *xpath,
894 const void *list_entry)
e9ce224b 895{
5707da09
RW
896 const struct agg_node *rn = list_entry;
897 const struct ripng_info *rinfo = listnode_head(rn->info);
80cf4e45 898 const struct ripng *ripng = ripng_info_get_instance(rinfo);
5707da09
RW
899
900 return yang_data_new_string(
80cf4e45 901 xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id));
e9ce224b
RW
902}
903
904/*
80cf4e45 905 * XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric
e9ce224b
RW
906 */
907static struct yang_data *
80cf4e45
RW
908ripngd_instance_state_routes_route_metric_get_elem(const char *xpath,
909 const void *list_entry)
e9ce224b 910{
5707da09
RW
911 const struct agg_node *rn = list_entry;
912 const struct ripng_info *rinfo = listnode_head(rn->info);
913
914 return yang_data_new_uint8(xpath, rinfo->metric);
e9ce224b
RW
915}
916
917/*
918 * XPath: /frr-ripngd:clear-ripng-route
919 */
c5b2b5f6 920static void clear_ripng_route(struct ripng *ripng)
e9ce224b 921{
49e06d25 922 struct agg_node *rp;
49e06d25 923
c5b2b5f6
RW
924 if (IS_RIPNG_DEBUG_EVENT)
925 zlog_debug("Clearing all RIPng routes (VRF %s)",
926 ripng->vrf_name);
bb5d09c9 927
49e06d25
RW
928 /* Clear received RIPng routes */
929 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
c5b2b5f6
RW
930 struct list *list;
931 struct listnode *listnode;
932 struct ripng_info *rinfo;
933
49e06d25
RW
934 list = rp->info;
935 if (list == NULL)
936 continue;
937
938 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
939 if (!ripng_route_rte(rinfo))
940 continue;
941
942 if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
5c84b9a5 943 ripng_zebra_ipv6_delete(ripng, rp);
49e06d25
RW
944 break;
945 }
946
947 if (rinfo) {
948 RIPNG_TIMER_OFF(rinfo->t_timeout);
949 RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
950 listnode_delete(list, rinfo);
951 ripng_info_free(rinfo);
952 }
953
954 if (list_isempty(list)) {
955 list_delete(&list);
956 rp->info = NULL;
957 agg_unlock_node(rp);
958 }
959 }
c5b2b5f6
RW
960}
961
962static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
963 struct list *output)
964{
965 struct ripng *ripng;
966 struct yang_data *yang_vrf;
967
968 yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf");
969 if (yang_vrf) {
970 ripng = ripng_lookup_by_vrf_name(yang_vrf->value);
971 if (ripng)
972 clear_ripng_route(ripng);
973 } else {
974 struct vrf *vrf;
975
976 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
977 ripng = vrf->info;
978 if (!ripng)
979 continue;
980
981 clear_ripng_route(ripng);
982 }
983 }
49e06d25 984
e9ce224b
RW
985 return NB_OK;
986}
987
988/*
989 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
990 */
991static int
992lib_interface_ripng_split_horizon_modify(enum nb_event event,
993 const struct lyd_node *dnode,
994 union nb_resource *resource)
995{
d406db4c
RW
996 struct interface *ifp;
997 struct ripng_interface *ri;
998
999 if (event != NB_EV_APPLY)
1000 return NB_OK;
1001
1002 ifp = yang_dnode_get_entry(dnode, true);
1003 ri = ifp->info;
1004 ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
1005
e9ce224b
RW
1006 return NB_OK;
1007}
1008
1009/* clang-format off */
1010const struct frr_yang_module_info frr_ripngd_info = {
1011 .name = "frr-ripngd",
1012 .nodes = {
1013 {
1014 .xpath = "/frr-ripngd:ripngd/instance",
1015 .cbs.create = ripngd_instance_create,
d01b92fd 1016 .cbs.destroy = ripngd_instance_delete,
80cf4e45
RW
1017 .cbs.get_next = ripngd_instance_get_next,
1018 .cbs.get_keys = ripngd_instance_get_keys,
1019 .cbs.lookup_entry = ripngd_instance_lookup_entry,
9a12e9e5 1020 .cbs.cli_show = cli_show_router_ripng,
e9ce224b
RW
1021 },
1022 {
1023 .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
1024 .cbs.modify = ripngd_instance_allow_ecmp_modify,
1e42a07c 1025 .cbs.cli_show = cli_show_ripng_allow_ecmp,
e9ce224b
RW
1026 },
1027 {
1028 .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
1029 .cbs.modify = ripngd_instance_default_information_originate_modify,
54b56562 1030 .cbs.cli_show = cli_show_ripng_default_information_originate,
e9ce224b
RW
1031 },
1032 {
1033 .xpath = "/frr-ripngd:ripngd/instance/default-metric",
1034 .cbs.modify = ripngd_instance_default_metric_modify,
ad8778c0 1035 .cbs.cli_show = cli_show_ripng_default_metric,
e9ce224b
RW
1036 },
1037 {
1038 .xpath = "/frr-ripngd:ripngd/instance/network",
1039 .cbs.create = ripngd_instance_network_create,
d01b92fd 1040 .cbs.destroy = ripngd_instance_network_delete,
cc48702b 1041 .cbs.cli_show = cli_show_ripng_network_prefix,
e9ce224b
RW
1042 },
1043 {
1044 .xpath = "/frr-ripngd:ripngd/instance/interface",
1045 .cbs.create = ripngd_instance_interface_create,
d01b92fd 1046 .cbs.destroy = ripngd_instance_interface_delete,
cc48702b 1047 .cbs.cli_show = cli_show_ripng_network_interface,
e9ce224b
RW
1048 },
1049 {
1050 .xpath = "/frr-ripngd:ripngd/instance/offset-list",
1051 .cbs.create = ripngd_instance_offset_list_create,
d01b92fd 1052 .cbs.destroy = ripngd_instance_offset_list_delete,
b09956ca 1053 .cbs.cli_show = cli_show_ripng_offset_list,
e9ce224b
RW
1054 },
1055 {
1056 .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list",
1057 .cbs.modify = ripngd_instance_offset_list_access_list_modify,
1058 },
1059 {
1060 .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric",
1061 .cbs.modify = ripngd_instance_offset_list_metric_modify,
1062 },
1063 {
1064 .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
1065 .cbs.create = ripngd_instance_passive_interface_create,
d01b92fd 1066 .cbs.destroy = ripngd_instance_passive_interface_delete,
22e8c7ae 1067 .cbs.cli_show = cli_show_ripng_passive_interface,
e9ce224b
RW
1068 },
1069 {
1070 .xpath = "/frr-ripngd:ripngd/instance/redistribute",
1071 .cbs.create = ripngd_instance_redistribute_create,
d01b92fd 1072 .cbs.destroy = ripngd_instance_redistribute_delete,
db2038c7
RW
1073 .cbs.apply_finish = ripngd_instance_redistribute_apply_finish,
1074 .cbs.cli_show = cli_show_ripng_redistribute,
e9ce224b
RW
1075 },
1076 {
1077 .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
1078 .cbs.modify = ripngd_instance_redistribute_route_map_modify,
d01b92fd 1079 .cbs.destroy = ripngd_instance_redistribute_route_map_delete,
e9ce224b
RW
1080 },
1081 {
1082 .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
1083 .cbs.modify = ripngd_instance_redistribute_metric_modify,
d01b92fd 1084 .cbs.destroy = ripngd_instance_redistribute_metric_delete,
e9ce224b
RW
1085 },
1086 {
1087 .xpath = "/frr-ripngd:ripngd/instance/static-route",
1088 .cbs.create = ripngd_instance_static_route_create,
d01b92fd 1089 .cbs.destroy = ripngd_instance_static_route_delete,
521d1b12 1090 .cbs.cli_show = cli_show_ripng_route,
e9ce224b
RW
1091 },
1092 {
1093 .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
1094 .cbs.create = ripngd_instance_aggregate_address_create,
d01b92fd 1095 .cbs.destroy = ripngd_instance_aggregate_address_delete,
6fc29385 1096 .cbs.cli_show = cli_show_ripng_aggregate_address,
e9ce224b 1097 },
f8981ec5
RW
1098 {
1099 .xpath = "/frr-ripngd:ripngd/instance/timers",
1100 .cbs.apply_finish = ripngd_instance_timers_apply_finish,
1101 .cbs.cli_show = cli_show_ripng_timers,
1102 },
e9ce224b
RW
1103 {
1104 .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval",
1105 .cbs.modify = ripngd_instance_timers_flush_interval_modify,
1106 },
1107 {
1108 .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval",
1109 .cbs.modify = ripngd_instance_timers_holddown_interval_modify,
1110 },
1111 {
1112 .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval",
1113 .cbs.modify = ripngd_instance_timers_update_interval_modify,
1114 },
1115 {
80cf4e45
RW
1116 .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor",
1117 .cbs.get_next = ripngd_instance_state_neighbors_neighbor_get_next,
1118 .cbs.get_keys = ripngd_instance_state_neighbors_neighbor_get_keys,
1119 .cbs.lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry,
e9ce224b
RW
1120 },
1121 {
80cf4e45
RW
1122 .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address",
1123 .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem,
e9ce224b
RW
1124 },
1125 {
80cf4e45
RW
1126 .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update",
1127 .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem,
e9ce224b
RW
1128 },
1129 {
80cf4e45
RW
1130 .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd",
1131 .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
e9ce224b
RW
1132 },
1133 {
80cf4e45
RW
1134 .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd",
1135 .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
e9ce224b
RW
1136 },
1137 {
80cf4e45
RW
1138 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route",
1139 .cbs.get_next = ripngd_instance_state_routes_route_get_next,
1140 .cbs.get_keys = ripngd_instance_state_routes_route_get_keys,
1141 .cbs.lookup_entry = ripngd_instance_state_routes_route_lookup_entry,
e9ce224b
RW
1142 },
1143 {
80cf4e45
RW
1144 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix",
1145 .cbs.get_elem = ripngd_instance_state_routes_route_prefix_get_elem,
e9ce224b
RW
1146 },
1147 {
80cf4e45
RW
1148 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop",
1149 .cbs.get_elem = ripngd_instance_state_routes_route_next_hop_get_elem,
e9ce224b
RW
1150 },
1151 {
80cf4e45
RW
1152 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface",
1153 .cbs.get_elem = ripngd_instance_state_routes_route_interface_get_elem,
e9ce224b
RW
1154 },
1155 {
80cf4e45
RW
1156 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric",
1157 .cbs.get_elem = ripngd_instance_state_routes_route_metric_get_elem,
e9ce224b
RW
1158 },
1159 {
1160 .xpath = "/frr-ripngd:clear-ripng-route",
1161 .cbs.rpc = clear_ripng_route_rpc,
1162 },
1163 {
1164 .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
1165 .cbs.modify = lib_interface_ripng_split_horizon_modify,
d406db4c 1166 .cbs.cli_show = cli_show_ipv6_ripng_split_horizon,
e9ce224b
RW
1167 },
1168 {
1169 .xpath = NULL,
1170 },
1171 }
1172};