]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_northbound.c
lib: fix outdated candidate configuration issue
[mirror_frr.git] / ripngd / ripng_northbound.c
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"
30 #include "agg_table.h"
31 #include "northbound.h"
32 #include "libfrr.h"
33
34 #include "ripngd/ripngd.h"
35 #include "ripngd/ripng_debug.h"
36 #include "ripngd/ripng_route.h"
37 #include "ripngd/ripng_cli.h"
38
39 /*
40 * XPath: /frr-ripngd:ripngd/instance
41 */
42 static int ripngd_instance_create(enum nb_event event,
43 const struct lyd_node *dnode,
44 union nb_resource *resource)
45 {
46 struct ripng *ripng;
47 struct vrf *vrf;
48 const char *vrf_name;
49 int socket;
50
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 */
58 switch (event) {
59 case NB_EV_VALIDATE:
60 break;
61 case NB_EV_PREPARE:
62 if (!vrf || !vrf_is_enabled(vrf))
63 break;
64
65 socket = ripng_make_socket(vrf);
66 if (socket < 0)
67 return NB_ERR_RESOURCE;
68 resource->fd = socket;
69 break;
70 case NB_EV_ABORT:
71 if (!vrf || !vrf_is_enabled(vrf))
72 break;
73
74 socket = resource->fd;
75 close(socket);
76 break;
77 case NB_EV_APPLY:
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);
84 nb_running_set_entry(dnode, ripng);
85 break;
86 }
87
88 return NB_OK;
89 }
90
91 static int ripngd_instance_destroy(enum nb_event event,
92 const struct lyd_node *dnode)
93 {
94 struct ripng *ripng;
95
96 if (event != NB_EV_APPLY)
97 return NB_OK;
98
99 ripng = nb_running_unset_entry(dnode);
100 ripng_clean(ripng);
101
102 return NB_OK;
103 }
104
105 static 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
118 static 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
129 static const void *
130 ripngd_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
138 /*
139 * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
140 */
141 static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
142 const struct lyd_node *dnode,
143 union nb_resource *resource)
144 {
145 struct ripng *ripng;
146
147 if (event != NB_EV_APPLY)
148 return NB_OK;
149
150 ripng = nb_running_get_entry(dnode, NULL, true);
151 ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
152 if (!ripng->ecmp)
153 ripng_ecmp_disable(ripng);
154
155 return NB_OK;
156 }
157
158 /*
159 * XPath: /frr-ripngd:ripngd/instance/default-information-originate
160 */
161 static int ripngd_instance_default_information_originate_modify(
162 enum nb_event event, const struct lyd_node *dnode,
163 union nb_resource *resource)
164 {
165 struct ripng *ripng;
166 bool default_information;
167 struct prefix_ipv6 p;
168
169 if (event != NB_EV_APPLY)
170 return NB_OK;
171
172 ripng = nb_running_get_entry(dnode, NULL, true);
173 default_information = yang_dnode_get_bool(dnode, NULL);
174
175 str2prefix_ipv6("::/0", &p);
176 if (default_information) {
177 ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
178 RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
179 } else {
180 ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
181 RIPNG_ROUTE_DEFAULT, &p, 0);
182 }
183
184 return NB_OK;
185 }
186
187 /*
188 * XPath: /frr-ripngd:ripngd/instance/default-metric
189 */
190 static int ripngd_instance_default_metric_modify(enum nb_event event,
191 const struct lyd_node *dnode,
192 union nb_resource *resource)
193 {
194 struct ripng *ripng;
195
196 if (event != NB_EV_APPLY)
197 return NB_OK;
198
199 ripng = nb_running_get_entry(dnode, NULL, true);
200 ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
201
202 return NB_OK;
203 }
204
205 /*
206 * XPath: /frr-ripngd:ripngd/instance/network
207 */
208 static int ripngd_instance_network_create(enum nb_event event,
209 const struct lyd_node *dnode,
210 union nb_resource *resource)
211 {
212 struct ripng *ripng;
213 struct prefix p;
214
215 if (event != NB_EV_APPLY)
216 return NB_OK;
217
218 ripng = nb_running_get_entry(dnode, NULL, true);
219 yang_dnode_get_ipv6p(&p, dnode, NULL);
220 apply_mask_ipv6((struct prefix_ipv6 *)&p);
221
222 return ripng_enable_network_add(ripng, &p);
223 }
224
225 static int ripngd_instance_network_destroy(enum nb_event event,
226 const struct lyd_node *dnode)
227 {
228 struct ripng *ripng;
229 struct prefix p;
230
231 if (event != NB_EV_APPLY)
232 return NB_OK;
233
234 ripng = nb_running_get_entry(dnode, NULL, true);
235 yang_dnode_get_ipv6p(&p, dnode, NULL);
236 apply_mask_ipv6((struct prefix_ipv6 *)&p);
237
238 return ripng_enable_network_delete(ripng, &p);
239 }
240
241 /*
242 * XPath: /frr-ripngd:ripngd/instance/interface
243 */
244 static int ripngd_instance_interface_create(enum nb_event event,
245 const struct lyd_node *dnode,
246 union nb_resource *resource)
247 {
248 struct ripng *ripng;
249 const char *ifname;
250
251 if (event != NB_EV_APPLY)
252 return NB_OK;
253
254 ripng = nb_running_get_entry(dnode, NULL, true);
255 ifname = yang_dnode_get_string(dnode, NULL);
256
257 return ripng_enable_if_add(ripng, ifname);
258 }
259
260 static int ripngd_instance_interface_destroy(enum nb_event event,
261 const struct lyd_node *dnode)
262 {
263 struct ripng *ripng;
264 const char *ifname;
265
266 if (event != NB_EV_APPLY)
267 return NB_OK;
268
269 ripng = nb_running_get_entry(dnode, NULL, true);
270 ifname = yang_dnode_get_string(dnode, NULL);
271
272 return ripng_enable_if_delete(ripng, ifname);
273 }
274
275 /*
276 * XPath: /frr-ripngd:ripngd/instance/offset-list
277 */
278 static int ripngd_instance_offset_list_create(enum nb_event event,
279 const struct lyd_node *dnode,
280 union nb_resource *resource)
281 {
282 struct ripng *ripng;
283 const char *ifname;
284 struct ripng_offset_list *offset;
285
286 if (event != NB_EV_APPLY)
287 return NB_OK;
288
289 ripng = nb_running_get_entry(dnode, NULL, true);
290 ifname = yang_dnode_get_string(dnode, "./interface");
291
292 offset = ripng_offset_list_new(ripng, ifname);
293 nb_running_set_entry(dnode, offset);
294
295 return NB_OK;
296 }
297
298 static int ripngd_instance_offset_list_destroy(enum nb_event event,
299 const struct lyd_node *dnode)
300 {
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 = nb_running_unset_entry(dnode);
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
318 return NB_OK;
319 }
320
321 /*
322 * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
323 */
324 static int
325 ripngd_instance_offset_list_access_list_modify(enum nb_event event,
326 const struct lyd_node *dnode,
327 union nb_resource *resource)
328 {
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 = nb_running_get_entry(dnode, NULL, 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
344 return NB_OK;
345 }
346
347 /*
348 * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
349 */
350 static int
351 ripngd_instance_offset_list_metric_modify(enum nb_event event,
352 const struct lyd_node *dnode,
353 union nb_resource *resource)
354 {
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 = nb_running_get_entry(dnode, NULL, true);
366 offset->direct[direct].metric = metric;
367
368 return NB_OK;
369 }
370
371 /*
372 * XPath: /frr-ripngd:ripngd/instance/passive-interface
373 */
374 static int
375 ripngd_instance_passive_interface_create(enum nb_event event,
376 const struct lyd_node *dnode,
377 union nb_resource *resource)
378 {
379 struct ripng *ripng;
380 const char *ifname;
381
382 if (event != NB_EV_APPLY)
383 return NB_OK;
384
385 ripng = nb_running_get_entry(dnode, NULL, true);
386 ifname = yang_dnode_get_string(dnode, NULL);
387
388 return ripng_passive_interface_set(ripng, ifname);
389 }
390
391 static int
392 ripngd_instance_passive_interface_destroy(enum nb_event event,
393 const struct lyd_node *dnode)
394 {
395 struct ripng *ripng;
396 const char *ifname;
397
398 if (event != NB_EV_APPLY)
399 return NB_OK;
400
401 ripng = nb_running_get_entry(dnode, NULL, true);
402 ifname = yang_dnode_get_string(dnode, NULL);
403
404 return ripng_passive_interface_unset(ripng, ifname);
405 }
406
407 /*
408 * XPath: /frr-ripngd:ripngd/instance/redistribute
409 */
410 static int ripngd_instance_redistribute_create(enum nb_event event,
411 const struct lyd_node *dnode,
412 union nb_resource *resource)
413 {
414 struct ripng *ripng;
415 int type;
416
417 if (event != NB_EV_APPLY)
418 return NB_OK;
419
420 ripng = nb_running_get_entry(dnode, NULL, true);
421 type = yang_dnode_get_enum(dnode, "./protocol");
422
423 ripng->redist[type].enabled = true;
424
425 return NB_OK;
426 }
427
428 static int ripngd_instance_redistribute_destroy(enum nb_event event,
429 const struct lyd_node *dnode)
430 {
431 struct ripng *ripng;
432 int type;
433
434 if (event != NB_EV_APPLY)
435 return NB_OK;
436
437 ripng = nb_running_get_entry(dnode, NULL, true);
438 type = yang_dnode_get_enum(dnode, "./protocol");
439
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);
451
452 return NB_OK;
453 }
454
455 static void
456 ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
457 {
458 struct ripng *ripng;
459 int type;
460
461 ripng = nb_running_get_entry(dnode, NULL, true);
462 type = yang_dnode_get_enum(dnode, "./protocol");
463
464 if (ripng->enabled)
465 ripng_redistribute_conf_update(ripng, type);
466 }
467
468 /*
469 * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
470 */
471 static int
472 ripngd_instance_redistribute_route_map_modify(enum nb_event event,
473 const struct lyd_node *dnode,
474 union nb_resource *resource)
475 {
476 struct ripng *ripng;
477 int type;
478 const char *rmap_name;
479
480 if (event != NB_EV_APPLY)
481 return NB_OK;
482
483 ripng = nb_running_get_entry(dnode, NULL, true);
484 type = yang_dnode_get_enum(dnode, "../protocol");
485 rmap_name = yang_dnode_get_string(dnode, NULL);
486
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);
491
492 return NB_OK;
493 }
494
495 static int
496 ripngd_instance_redistribute_route_map_destroy(enum nb_event event,
497 const struct lyd_node *dnode)
498 {
499 struct ripng *ripng;
500 int type;
501
502 if (event != NB_EV_APPLY)
503 return NB_OK;
504
505 ripng = nb_running_get_entry(dnode, NULL, true);
506 type = yang_dnode_get_enum(dnode, "../protocol");
507
508 free(ripng->redist[type].route_map.name);
509 ripng->redist[type].route_map.name = NULL;
510 ripng->redist[type].route_map.map = NULL;
511
512 return NB_OK;
513 }
514
515 /*
516 * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
517 */
518 static int
519 ripngd_instance_redistribute_metric_modify(enum nb_event event,
520 const struct lyd_node *dnode,
521 union nb_resource *resource)
522 {
523 struct ripng *ripng;
524 int type;
525 uint8_t metric;
526
527 if (event != NB_EV_APPLY)
528 return NB_OK;
529
530 ripng = nb_running_get_entry(dnode, NULL, true);
531 type = yang_dnode_get_enum(dnode, "../protocol");
532 metric = yang_dnode_get_uint8(dnode, NULL);
533
534 ripng->redist[type].metric_config = true;
535 ripng->redist[type].metric = metric;
536
537 return NB_OK;
538 }
539
540 static int
541 ripngd_instance_redistribute_metric_destroy(enum nb_event event,
542 const struct lyd_node *dnode)
543 {
544 struct ripng *ripng;
545 int type;
546
547 if (event != NB_EV_APPLY)
548 return NB_OK;
549
550 ripng = nb_running_get_entry(dnode, NULL, true);
551 type = yang_dnode_get_enum(dnode, "../protocol");
552
553 ripng->redist[type].metric_config = false;
554 ripng->redist[type].metric = 0;
555
556 return NB_OK;
557 }
558
559 /*
560 * XPath: /frr-ripngd:ripngd/instance/static-route
561 */
562 static int ripngd_instance_static_route_create(enum nb_event event,
563 const struct lyd_node *dnode,
564 union nb_resource *resource)
565 {
566 struct ripng *ripng;
567 struct prefix_ipv6 p;
568
569 if (event != NB_EV_APPLY)
570 return NB_OK;
571
572 ripng = nb_running_get_entry(dnode, NULL, true);
573 yang_dnode_get_ipv6p(&p, dnode, NULL);
574 apply_mask_ipv6(&p);
575
576 ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
577 0, NULL, 0);
578
579 return NB_OK;
580 }
581
582 static int ripngd_instance_static_route_destroy(enum nb_event event,
583 const struct lyd_node *dnode)
584 {
585 struct ripng *ripng;
586 struct prefix_ipv6 p;
587
588 if (event != NB_EV_APPLY)
589 return NB_OK;
590
591 ripng = nb_running_get_entry(dnode, NULL, true);
592 yang_dnode_get_ipv6p(&p, dnode, NULL);
593 apply_mask_ipv6(&p);
594
595 ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
596 &p, 0);
597
598 return NB_OK;
599 }
600
601 /*
602 * XPath: /frr-ripngd:ripngd/instance/aggregate-address
603 */
604 static int
605 ripngd_instance_aggregate_address_create(enum nb_event event,
606 const struct lyd_node *dnode,
607 union nb_resource *resource)
608 {
609 struct ripng *ripng;
610 struct prefix_ipv6 p;
611
612 if (event != NB_EV_APPLY)
613 return NB_OK;
614
615 ripng = nb_running_get_entry(dnode, NULL, true);
616 yang_dnode_get_ipv6p(&p, dnode, NULL);
617 apply_mask_ipv6(&p);
618
619 ripng_aggregate_add(ripng, (struct prefix *)&p);
620
621 return NB_OK;
622 }
623
624 static int
625 ripngd_instance_aggregate_address_destroy(enum nb_event event,
626 const struct lyd_node *dnode)
627 {
628 struct ripng *ripng;
629 struct prefix_ipv6 p;
630
631 if (event != NB_EV_APPLY)
632 return NB_OK;
633
634 ripng = nb_running_get_entry(dnode, NULL, true);
635 yang_dnode_get_ipv6p(&p, dnode, NULL);
636 apply_mask_ipv6(&p);
637
638 ripng_aggregate_delete(ripng, (struct prefix *)&p);
639
640 return NB_OK;
641 }
642
643 /*
644 * XPath: /frr-ripngd:ripngd/instance/timers
645 */
646 static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
647 {
648 struct ripng *ripng;
649
650 ripng = nb_running_get_entry(dnode, NULL, true);
651
652 /* Reset update timer thread. */
653 ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
654 }
655
656 /*
657 * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
658 */
659 static int
660 ripngd_instance_timers_flush_interval_modify(enum nb_event event,
661 const struct lyd_node *dnode,
662 union nb_resource *resource)
663 {
664 struct ripng *ripng;
665
666 if (event != NB_EV_APPLY)
667 return NB_OK;
668
669 ripng = nb_running_get_entry(dnode, NULL, true);
670 ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
671
672 return NB_OK;
673 }
674
675 /*
676 * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
677 */
678 static int
679 ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
680 const struct lyd_node *dnode,
681 union nb_resource *resource)
682 {
683 struct ripng *ripng;
684
685 if (event != NB_EV_APPLY)
686 return NB_OK;
687
688 ripng = nb_running_get_entry(dnode, NULL, true);
689 ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
690
691 return NB_OK;
692 }
693
694 /*
695 * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
696 */
697 static int
698 ripngd_instance_timers_update_interval_modify(enum nb_event event,
699 const struct lyd_node *dnode,
700 union nb_resource *resource)
701 {
702 struct ripng *ripng;
703
704 if (event != NB_EV_APPLY)
705 return NB_OK;
706
707 ripng = nb_running_get_entry(dnode, NULL, true);
708 ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
709
710 return NB_OK;
711 }
712
713 /*
714 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor
715 */
716 static const void *
717 ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
718 const void *list_entry)
719 {
720 const struct ripng *ripng = parent_list_entry;
721 struct listnode *node;
722
723 if (list_entry == NULL)
724 node = listhead(ripng->peer_list);
725 else
726 node = listnextnode((struct listnode *)list_entry);
727
728 return node;
729 }
730
731 static int
732 ripngd_instance_state_neighbors_neighbor_get_keys(const void *list_entry,
733 struct yang_list_keys *keys)
734 {
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
742 return NB_OK;
743 }
744
745 static const void *ripngd_instance_state_neighbors_neighbor_lookup_entry(
746 const void *parent_list_entry, const struct yang_list_keys *keys)
747 {
748 const struct ripng *ripng = parent_list_entry;
749 struct in6_addr address;
750 struct ripng_peer *peer;
751 struct listnode *node;
752
753 yang_str2ipv6(keys->key[0], &address);
754
755 for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) {
756 if (IPV6_ADDR_SAME(&peer->addr, &address))
757 return node;
758 }
759
760 return NULL;
761 }
762
763 /*
764 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address
765 */
766 static struct yang_data *
767 ripngd_instance_state_neighbors_neighbor_address_get_elem(
768 const char *xpath, const void *list_entry)
769 {
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);
774 }
775
776 /*
777 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update
778 */
779 static struct yang_data *
780 ripngd_instance_state_neighbors_neighbor_last_update_get_elem(
781 const char *xpath, const void *list_entry)
782 {
783 /* TODO: yang:date-and-time is tricky */
784 return NULL;
785 }
786
787 /*
788 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd
789 */
790 static struct yang_data *
791 ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
792 const char *xpath, const void *list_entry)
793 {
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);
798 }
799
800 /*
801 * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd
802 */
803 static struct yang_data *
804 ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
805 const char *xpath, const void *list_entry)
806 {
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);
811 }
812
813 /*
814 * XPath: /frr-ripngd:ripngd/instance/state/routes/route
815 */
816 static const void *
817 ripngd_instance_state_routes_route_get_next(const void *parent_list_entry,
818 const void *list_entry)
819 {
820 const struct ripng *ripng = parent_list_entry;
821 struct agg_node *rn;
822
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;
831 }
832
833 static int
834 ripngd_instance_state_routes_route_get_keys(const void *list_entry,
835 struct yang_list_keys *keys)
836 {
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
842 return NB_OK;
843 }
844
845 static const void *ripngd_instance_state_routes_route_lookup_entry(
846 const void *parent_list_entry, const struct yang_list_keys *keys)
847 {
848 const struct ripng *ripng = parent_list_entry;
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;
861 }
862
863 /*
864 * XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix
865 */
866 static struct yang_data *
867 ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath,
868 const void *list_entry)
869 {
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);
874 }
875
876 /*
877 * XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop
878 */
879 static struct yang_data *
880 ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
881 const void *list_entry)
882 {
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);
887 }
888
889 /*
890 * XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface
891 */
892 static struct yang_data *
893 ripngd_instance_state_routes_route_interface_get_elem(const char *xpath,
894 const void *list_entry)
895 {
896 const struct agg_node *rn = list_entry;
897 const struct ripng_info *rinfo = listnode_head(rn->info);
898 const struct ripng *ripng = ripng_info_get_instance(rinfo);
899
900 return yang_data_new_string(
901 xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id));
902 }
903
904 /*
905 * XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric
906 */
907 static struct yang_data *
908 ripngd_instance_state_routes_route_metric_get_elem(const char *xpath,
909 const void *list_entry)
910 {
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);
915 }
916
917 /*
918 * XPath: /frr-ripngd:clear-ripng-route
919 */
920 static void clear_ripng_route(struct ripng *ripng)
921 {
922 struct agg_node *rp;
923
924 if (IS_RIPNG_DEBUG_EVENT)
925 zlog_debug("Clearing all RIPng routes (VRF %s)",
926 ripng->vrf_name);
927
928 /* Clear received RIPng routes */
929 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
930 struct list *list;
931 struct listnode *listnode;
932 struct ripng_info *rinfo;
933
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))
943 ripng_zebra_ipv6_delete(ripng, rp);
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 }
960 }
961
962 static 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 }
984
985 return NB_OK;
986 }
987
988 /*
989 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
990 */
991 static int
992 lib_interface_ripng_split_horizon_modify(enum nb_event event,
993 const struct lyd_node *dnode,
994 union nb_resource *resource)
995 {
996 struct interface *ifp;
997 struct ripng_interface *ri;
998
999 if (event != NB_EV_APPLY)
1000 return NB_OK;
1001
1002 ifp = nb_running_get_entry(dnode, NULL, true);
1003 ri = ifp->info;
1004 ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
1005
1006 return NB_OK;
1007 }
1008
1009 /* clang-format off */
1010 const 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,
1016 .cbs.destroy = ripngd_instance_destroy,
1017 .cbs.get_next = ripngd_instance_get_next,
1018 .cbs.get_keys = ripngd_instance_get_keys,
1019 .cbs.lookup_entry = ripngd_instance_lookup_entry,
1020 .cbs.cli_show = cli_show_router_ripng,
1021 },
1022 {
1023 .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
1024 .cbs.modify = ripngd_instance_allow_ecmp_modify,
1025 .cbs.cli_show = cli_show_ripng_allow_ecmp,
1026 },
1027 {
1028 .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
1029 .cbs.modify = ripngd_instance_default_information_originate_modify,
1030 .cbs.cli_show = cli_show_ripng_default_information_originate,
1031 },
1032 {
1033 .xpath = "/frr-ripngd:ripngd/instance/default-metric",
1034 .cbs.modify = ripngd_instance_default_metric_modify,
1035 .cbs.cli_show = cli_show_ripng_default_metric,
1036 },
1037 {
1038 .xpath = "/frr-ripngd:ripngd/instance/network",
1039 .cbs.create = ripngd_instance_network_create,
1040 .cbs.destroy = ripngd_instance_network_destroy,
1041 .cbs.cli_show = cli_show_ripng_network_prefix,
1042 },
1043 {
1044 .xpath = "/frr-ripngd:ripngd/instance/interface",
1045 .cbs.create = ripngd_instance_interface_create,
1046 .cbs.destroy = ripngd_instance_interface_destroy,
1047 .cbs.cli_show = cli_show_ripng_network_interface,
1048 },
1049 {
1050 .xpath = "/frr-ripngd:ripngd/instance/offset-list",
1051 .cbs.create = ripngd_instance_offset_list_create,
1052 .cbs.destroy = ripngd_instance_offset_list_destroy,
1053 .cbs.cli_show = cli_show_ripng_offset_list,
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,
1066 .cbs.destroy = ripngd_instance_passive_interface_destroy,
1067 .cbs.cli_show = cli_show_ripng_passive_interface,
1068 },
1069 {
1070 .xpath = "/frr-ripngd:ripngd/instance/redistribute",
1071 .cbs.create = ripngd_instance_redistribute_create,
1072 .cbs.destroy = ripngd_instance_redistribute_destroy,
1073 .cbs.apply_finish = ripngd_instance_redistribute_apply_finish,
1074 .cbs.cli_show = cli_show_ripng_redistribute,
1075 },
1076 {
1077 .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
1078 .cbs.modify = ripngd_instance_redistribute_route_map_modify,
1079 .cbs.destroy = ripngd_instance_redistribute_route_map_destroy,
1080 },
1081 {
1082 .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
1083 .cbs.modify = ripngd_instance_redistribute_metric_modify,
1084 .cbs.destroy = ripngd_instance_redistribute_metric_destroy,
1085 },
1086 {
1087 .xpath = "/frr-ripngd:ripngd/instance/static-route",
1088 .cbs.create = ripngd_instance_static_route_create,
1089 .cbs.destroy = ripngd_instance_static_route_destroy,
1090 .cbs.cli_show = cli_show_ripng_route,
1091 },
1092 {
1093 .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
1094 .cbs.create = ripngd_instance_aggregate_address_create,
1095 .cbs.destroy = ripngd_instance_aggregate_address_destroy,
1096 .cbs.cli_show = cli_show_ripng_aggregate_address,
1097 },
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 },
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 {
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,
1120 },
1121 {
1122 .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address",
1123 .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem,
1124 },
1125 {
1126 .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update",
1127 .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem,
1128 },
1129 {
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,
1132 },
1133 {
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,
1136 },
1137 {
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,
1142 },
1143 {
1144 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix",
1145 .cbs.get_elem = ripngd_instance_state_routes_route_prefix_get_elem,
1146 },
1147 {
1148 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop",
1149 .cbs.get_elem = ripngd_instance_state_routes_route_next_hop_get_elem,
1150 },
1151 {
1152 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface",
1153 .cbs.get_elem = ripngd_instance_state_routes_route_interface_get_elem,
1154 },
1155 {
1156 .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric",
1157 .cbs.get_elem = ripngd_instance_state_routes_route_metric_get_elem,
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,
1166 .cbs.cli_show = cli_show_ipv6_ripng_split_horizon,
1167 },
1168 {
1169 .xpath = NULL,
1170 },
1171 }
1172 };