]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_northbound.c
zebra: Allow ns delete to happen after under/over flow checks
[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_route.h"
36 #include "ripngd/ripng_cli.h"
37
38 /*
39 * XPath: /frr-ripngd:ripngd/instance
40 */
41 static int ripngd_instance_create(enum nb_event event,
42 const struct lyd_node *dnode,
43 union nb_resource *resource)
44 {
45 int socket;
46
47 switch (event) {
48 case NB_EV_VALIDATE:
49 break;
50 case NB_EV_PREPARE:
51 socket = ripng_make_socket();
52 if (socket < 0)
53 return NB_ERR_RESOURCE;
54 resource->fd = socket;
55 break;
56 case NB_EV_ABORT:
57 socket = resource->fd;
58 close(socket);
59 break;
60 case NB_EV_APPLY:
61 socket = resource->fd;
62 ripng_create(socket);
63 break;
64 }
65
66 return NB_OK;
67 }
68
69 static int ripngd_instance_delete(enum nb_event event,
70 const struct lyd_node *dnode)
71 {
72 if (event != NB_EV_APPLY)
73 return NB_OK;
74
75 ripng_clean();
76
77 return NB_OK;
78 }
79
80 /*
81 * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
82 */
83 static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
84 const struct lyd_node *dnode,
85 union nb_resource *resource)
86 {
87 if (event != NB_EV_APPLY)
88 return NB_OK;
89
90 ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
91 if (!ripng->ecmp)
92 ripng_ecmp_disable();
93
94 return NB_OK;
95 }
96
97 /*
98 * XPath: /frr-ripngd:ripngd/instance/default-information-originate
99 */
100 static int ripngd_instance_default_information_originate_modify(
101 enum nb_event event, const struct lyd_node *dnode,
102 union nb_resource *resource)
103 {
104 bool default_information;
105 struct prefix_ipv6 p;
106
107 if (event != NB_EV_APPLY)
108 return NB_OK;
109
110 default_information = yang_dnode_get_bool(dnode, NULL);
111 str2prefix_ipv6("::/0", &p);
112 if (default_information) {
113 ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT,
114 &p, 0, NULL, 0);
115 } else {
116 ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG,
117 RIPNG_ROUTE_DEFAULT, &p, 0);
118 }
119
120 return NB_OK;
121 }
122
123 /*
124 * XPath: /frr-ripngd:ripngd/instance/default-metric
125 */
126 static int ripngd_instance_default_metric_modify(enum nb_event event,
127 const struct lyd_node *dnode,
128 union nb_resource *resource)
129 {
130 if (event != NB_EV_APPLY)
131 return NB_OK;
132
133 ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
134
135 return NB_OK;
136 }
137
138 /*
139 * XPath: /frr-ripngd:ripngd/instance/network
140 */
141 static int ripngd_instance_network_create(enum nb_event event,
142 const struct lyd_node *dnode,
143 union nb_resource *resource)
144 {
145 struct prefix p;
146
147 if (event != NB_EV_APPLY)
148 return NB_OK;
149
150 yang_dnode_get_ipv6p(&p, dnode, NULL);
151 apply_mask_ipv6((struct prefix_ipv6 *)&p);
152
153 return ripng_enable_network_add(&p);
154 }
155
156 static int ripngd_instance_network_delete(enum nb_event event,
157 const struct lyd_node *dnode)
158 {
159 struct prefix p;
160
161 if (event != NB_EV_APPLY)
162 return NB_OK;
163
164 yang_dnode_get_ipv6p(&p, dnode, NULL);
165 apply_mask_ipv6((struct prefix_ipv6 *)&p);
166
167 return ripng_enable_network_delete(&p);
168 }
169
170 /*
171 * XPath: /frr-ripngd:ripngd/instance/interface
172 */
173 static int ripngd_instance_interface_create(enum nb_event event,
174 const struct lyd_node *dnode,
175 union nb_resource *resource)
176 {
177 const char *ifname;
178
179 if (event != NB_EV_APPLY)
180 return NB_OK;
181
182 ifname = yang_dnode_get_string(dnode, NULL);
183
184 return ripng_enable_if_add(ifname);
185 }
186
187 static int ripngd_instance_interface_delete(enum nb_event event,
188 const struct lyd_node *dnode)
189 {
190 const char *ifname;
191
192 if (event != NB_EV_APPLY)
193 return NB_OK;
194
195 ifname = yang_dnode_get_string(dnode, NULL);
196
197 return ripng_enable_if_delete(ifname);
198 }
199
200 /*
201 * XPath: /frr-ripngd:ripngd/instance/offset-list
202 */
203 static int ripngd_instance_offset_list_create(enum nb_event event,
204 const struct lyd_node *dnode,
205 union nb_resource *resource)
206 {
207 const char *ifname;
208 struct ripng_offset_list *offset;
209
210 if (event != NB_EV_APPLY)
211 return NB_OK;
212
213 ifname = yang_dnode_get_string(dnode, "./interface");
214
215 offset = ripng_offset_list_new(ifname);
216 yang_dnode_set_entry(dnode, offset);
217
218 return NB_OK;
219 }
220
221 static int ripngd_instance_offset_list_delete(enum nb_event event,
222 const struct lyd_node *dnode)
223 {
224 int direct;
225 struct ripng_offset_list *offset;
226
227 if (event != NB_EV_APPLY)
228 return NB_OK;
229
230 direct = yang_dnode_get_enum(dnode, "./direction");
231
232 offset = yang_dnode_get_entry(dnode, true);
233 if (offset->direct[direct].alist_name) {
234 free(offset->direct[direct].alist_name);
235 offset->direct[direct].alist_name = NULL;
236 }
237 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
238 && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
239 ripng_offset_list_del(offset);
240
241 return NB_OK;
242 }
243
244 /*
245 * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
246 */
247 static int
248 ripngd_instance_offset_list_access_list_modify(enum nb_event event,
249 const struct lyd_node *dnode,
250 union nb_resource *resource)
251 {
252 int direct;
253 struct ripng_offset_list *offset;
254 const char *alist_name;
255
256 if (event != NB_EV_APPLY)
257 return NB_OK;
258
259 direct = yang_dnode_get_enum(dnode, "../direction");
260 alist_name = yang_dnode_get_string(dnode, NULL);
261
262 offset = yang_dnode_get_entry(dnode, true);
263 if (offset->direct[direct].alist_name)
264 free(offset->direct[direct].alist_name);
265 offset->direct[direct].alist_name = strdup(alist_name);
266
267 return NB_OK;
268 }
269
270 /*
271 * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
272 */
273 static int
274 ripngd_instance_offset_list_metric_modify(enum nb_event event,
275 const struct lyd_node *dnode,
276 union nb_resource *resource)
277 {
278 int direct;
279 uint8_t metric;
280 struct ripng_offset_list *offset;
281
282 if (event != NB_EV_APPLY)
283 return NB_OK;
284
285 direct = yang_dnode_get_enum(dnode, "../direction");
286 metric = yang_dnode_get_uint8(dnode, NULL);
287
288 offset = yang_dnode_get_entry(dnode, true);
289 offset->direct[direct].metric = metric;
290
291 return NB_OK;
292 }
293
294 /*
295 * XPath: /frr-ripngd:ripngd/instance/passive-interface
296 */
297 static int
298 ripngd_instance_passive_interface_create(enum nb_event event,
299 const struct lyd_node *dnode,
300 union nb_resource *resource)
301 {
302 const char *ifname;
303
304 if (event != NB_EV_APPLY)
305 return NB_OK;
306
307 ifname = yang_dnode_get_string(dnode, NULL);
308
309 return ripng_passive_interface_set(ifname);
310 }
311
312 static int
313 ripngd_instance_passive_interface_delete(enum nb_event event,
314 const struct lyd_node *dnode)
315 {
316 const char *ifname;
317
318 if (event != NB_EV_APPLY)
319 return NB_OK;
320
321 ifname = yang_dnode_get_string(dnode, NULL);
322
323 return ripng_passive_interface_unset(ifname);
324 }
325
326 /*
327 * XPath: /frr-ripngd:ripngd/instance/redistribute
328 */
329 static int ripngd_instance_redistribute_create(enum nb_event event,
330 const struct lyd_node *dnode,
331 union nb_resource *resource)
332 {
333 return NB_OK;
334 }
335
336 static int ripngd_instance_redistribute_delete(enum nb_event event,
337 const struct lyd_node *dnode)
338 {
339 int type;
340
341 if (event != NB_EV_APPLY)
342 return NB_OK;
343
344 type = yang_dnode_get_enum(dnode, "./protocol");
345
346 ripng_redistribute_conf_delete(type);
347
348 return NB_OK;
349 }
350
351 static void
352 ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
353 {
354 int type;
355
356 type = yang_dnode_get_enum(dnode, "./protocol");
357 ripng_redistribute_conf_update(type);
358 }
359
360 /*
361 * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
362 */
363 static int
364 ripngd_instance_redistribute_route_map_modify(enum nb_event event,
365 const struct lyd_node *dnode,
366 union nb_resource *resource)
367 {
368 int type;
369 const char *rmap_name;
370
371 if (event != NB_EV_APPLY)
372 return NB_OK;
373
374 type = yang_dnode_get_enum(dnode, "../protocol");
375 rmap_name = yang_dnode_get_string(dnode, NULL);
376
377 if (ripng->route_map[type].name)
378 free(ripng->route_map[type].name);
379 ripng->route_map[type].name = strdup(rmap_name);
380 ripng->route_map[type].map = route_map_lookup_by_name(rmap_name);
381
382 return NB_OK;
383 }
384
385 static int
386 ripngd_instance_redistribute_route_map_delete(enum nb_event event,
387 const struct lyd_node *dnode)
388 {
389 int type;
390
391 if (event != NB_EV_APPLY)
392 return NB_OK;
393
394 type = yang_dnode_get_enum(dnode, "../protocol");
395
396 free(ripng->route_map[type].name);
397 ripng->route_map[type].name = NULL;
398 ripng->route_map[type].map = NULL;
399
400 return NB_OK;
401 }
402
403 /*
404 * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
405 */
406 static int
407 ripngd_instance_redistribute_metric_modify(enum nb_event event,
408 const struct lyd_node *dnode,
409 union nb_resource *resource)
410 {
411 int type;
412 uint8_t metric;
413
414 if (event != NB_EV_APPLY)
415 return NB_OK;
416
417 type = yang_dnode_get_enum(dnode, "../protocol");
418 metric = yang_dnode_get_uint8(dnode, NULL);
419
420 ripng->route_map[type].metric_config = true;
421 ripng->route_map[type].metric = metric;
422
423 return NB_OK;
424 }
425
426 static int
427 ripngd_instance_redistribute_metric_delete(enum nb_event event,
428 const struct lyd_node *dnode)
429 {
430 int type;
431
432 if (event != NB_EV_APPLY)
433 return NB_OK;
434
435 type = yang_dnode_get_enum(dnode, "../protocol");
436
437 ripng->route_map[type].metric_config = false;
438 ripng->route_map[type].metric = 0;
439
440 return NB_OK;
441 }
442
443 /*
444 * XPath: /frr-ripngd:ripngd/instance/static-route
445 */
446 static int ripngd_instance_static_route_create(enum nb_event event,
447 const struct lyd_node *dnode,
448 union nb_resource *resource)
449 {
450 struct prefix_ipv6 p;
451
452 if (event != NB_EV_APPLY)
453 return NB_OK;
454
455 yang_dnode_get_ipv6p(&p, dnode, NULL);
456 apply_mask_ipv6(&p);
457
458 ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0,
459 NULL, 0);
460
461 return NB_OK;
462 }
463
464 static int ripngd_instance_static_route_delete(enum nb_event event,
465 const struct lyd_node *dnode)
466 {
467 struct prefix_ipv6 p;
468
469 if (event != NB_EV_APPLY)
470 return NB_OK;
471
472 yang_dnode_get_ipv6p(&p, dnode, NULL);
473 apply_mask_ipv6(&p);
474
475 ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
476
477 return NB_OK;
478 }
479
480 /*
481 * XPath: /frr-ripngd:ripngd/instance/aggregate-address
482 */
483 static int
484 ripngd_instance_aggregate_address_create(enum nb_event event,
485 const struct lyd_node *dnode,
486 union nb_resource *resource)
487 {
488 struct prefix_ipv6 p;
489
490 if (event != NB_EV_APPLY)
491 return NB_OK;
492
493 yang_dnode_get_ipv6p(&p, dnode, NULL);
494 apply_mask_ipv6(&p);
495
496 ripng_aggregate_add((struct prefix *)&p);
497
498 return NB_OK;
499 }
500
501 static int
502 ripngd_instance_aggregate_address_delete(enum nb_event event,
503 const struct lyd_node *dnode)
504 {
505 struct prefix_ipv6 p;
506
507 if (event != NB_EV_APPLY)
508 return NB_OK;
509
510 yang_dnode_get_ipv6p(&p, dnode, NULL);
511 apply_mask_ipv6(&p);
512
513 ripng_aggregate_delete((struct prefix *)&p);
514
515 return NB_OK;
516 }
517
518 /*
519 * XPath: /frr-ripngd:ripngd/instance/timers
520 */
521 static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
522 {
523 /* Reset update timer thread. */
524 ripng_event(RIPNG_UPDATE_EVENT, 0);
525 }
526
527 /*
528 * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
529 */
530 static int
531 ripngd_instance_timers_flush_interval_modify(enum nb_event event,
532 const struct lyd_node *dnode,
533 union nb_resource *resource)
534 {
535 if (event != NB_EV_APPLY)
536 return NB_OK;
537
538 ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
539
540 return NB_OK;
541 }
542
543 /*
544 * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
545 */
546 static int
547 ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
548 const struct lyd_node *dnode,
549 union nb_resource *resource)
550 {
551 if (event != NB_EV_APPLY)
552 return NB_OK;
553
554 ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
555
556 return NB_OK;
557 }
558
559 /*
560 * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
561 */
562 static int
563 ripngd_instance_timers_update_interval_modify(enum nb_event event,
564 const struct lyd_node *dnode,
565 union nb_resource *resource)
566 {
567 if (event != NB_EV_APPLY)
568 return NB_OK;
569
570 ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
571
572 return NB_OK;
573 }
574
575 /*
576 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor
577 */
578 static const void *
579 ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
580 const void *list_entry)
581 {
582 struct listnode *node;
583
584 if (list_entry == NULL)
585 node = listhead(peer_list);
586 else
587 node = listnextnode((struct listnode *)list_entry);
588
589 return node;
590 }
591
592 static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
593 struct yang_list_keys *keys)
594 {
595 const struct listnode *node = list_entry;
596 const struct ripng_peer *peer = listgetdata(node);
597
598 keys->num = 1;
599 (void)inet_ntop(AF_INET6, &peer->addr, keys->key[0],
600 sizeof(keys->key[0]));
601
602 return NB_OK;
603 }
604
605 static const void *
606 ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
607 const struct yang_list_keys *keys)
608 {
609 struct in6_addr address;
610 struct ripng_peer *peer;
611 struct listnode *node;
612
613 yang_str2ipv6(keys->key[0], &address);
614
615 for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) {
616 if (IPV6_ADDR_SAME(&peer->addr, &address))
617 return node;
618 }
619
620 return NULL;
621 }
622
623 /*
624 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/address
625 */
626 static struct yang_data *
627 ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath,
628 const void *list_entry)
629 {
630 const struct listnode *node = list_entry;
631 const struct ripng_peer *peer = listgetdata(node);
632
633 return yang_data_new_ipv6(xpath, &peer->addr);
634 }
635
636 /*
637 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/last-update
638 */
639 static struct yang_data *
640 ripngd_state_neighbors_neighbor_last_update_get_elem(const char *xpath,
641 const void *list_entry)
642 {
643 /* TODO: yang:date-and-time is tricky */
644 return NULL;
645 }
646
647 /*
648 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd
649 */
650 static struct yang_data *
651 ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
652 const char *xpath, const void *list_entry)
653 {
654 const struct listnode *node = list_entry;
655 const struct ripng_peer *peer = listgetdata(node);
656
657 return yang_data_new_uint32(xpath, peer->recv_badpackets);
658 }
659
660 /*
661 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd
662 */
663 static struct yang_data *
664 ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
665 const void *list_entry)
666 {
667 const struct listnode *node = list_entry;
668 const struct ripng_peer *peer = listgetdata(node);
669
670 return yang_data_new_uint32(xpath, peer->recv_badroutes);
671 }
672
673 /*
674 * XPath: /frr-ripngd:ripngd/state/routes/route
675 */
676 static const void *
677 ripngd_state_routes_route_get_next(const void *parent_list_entry,
678 const void *list_entry)
679 {
680 struct agg_node *rn;
681
682 if (ripng == NULL)
683 return NULL;
684
685 if (list_entry == NULL)
686 rn = agg_route_top(ripng->table);
687 else
688 rn = agg_route_next((struct agg_node *)list_entry);
689 while (rn && rn->info == NULL)
690 rn = agg_route_next(rn);
691
692 return rn;
693 }
694
695 static int ripngd_state_routes_route_get_keys(const void *list_entry,
696 struct yang_list_keys *keys)
697 {
698 const struct agg_node *rn = list_entry;
699
700 keys->num = 1;
701 (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0]));
702
703 return NB_OK;
704 }
705
706 static const void *
707 ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
708 const struct yang_list_keys *keys)
709 {
710 struct prefix prefix;
711 struct agg_node *rn;
712
713 yang_str2ipv6p(keys->key[0], &prefix);
714
715 rn = agg_node_lookup(ripng->table, &prefix);
716 if (!rn || !rn->info)
717 return NULL;
718
719 agg_unlock_node(rn);
720
721 return rn;
722 }
723
724 /*
725 * XPath: /frr-ripngd:ripngd/state/routes/route/prefix
726 */
727 static struct yang_data *
728 ripngd_state_routes_route_prefix_get_elem(const char *xpath,
729 const void *list_entry)
730 {
731 const struct agg_node *rn = list_entry;
732 const struct ripng_info *rinfo = listnode_head(rn->info);
733
734 return yang_data_new_ipv6p(xpath, &rinfo->rp->p);
735 }
736
737 /*
738 * XPath: /frr-ripngd:ripngd/state/routes/route/next-hop
739 */
740 static struct yang_data *
741 ripngd_state_routes_route_next_hop_get_elem(const char *xpath,
742 const void *list_entry)
743 {
744 const struct agg_node *rn = list_entry;
745 const struct ripng_info *rinfo = listnode_head(rn->info);
746
747 return yang_data_new_ipv6(xpath, &rinfo->nexthop);
748 }
749
750 /*
751 * XPath: /frr-ripngd:ripngd/state/routes/route/interface
752 */
753 static struct yang_data *
754 ripngd_state_routes_route_interface_get_elem(const char *xpath,
755 const void *list_entry)
756 {
757 const struct agg_node *rn = list_entry;
758 const struct ripng_info *rinfo = listnode_head(rn->info);
759
760 return yang_data_new_string(
761 xpath, ifindex2ifname(rinfo->ifindex, VRF_DEFAULT));
762 }
763
764 /*
765 * XPath: /frr-ripngd:ripngd/state/routes/route/metric
766 */
767 static struct yang_data *
768 ripngd_state_routes_route_metric_get_elem(const char *xpath,
769 const void *list_entry)
770 {
771 const struct agg_node *rn = list_entry;
772 const struct ripng_info *rinfo = listnode_head(rn->info);
773
774 return yang_data_new_uint8(xpath, rinfo->metric);
775 }
776
777 /*
778 * XPath: /frr-ripngd:clear-ripng-route
779 */
780 static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
781 struct list *output)
782 {
783 struct agg_node *rp;
784 struct ripng_info *rinfo;
785 struct list *list;
786 struct listnode *listnode;
787
788 /* Clear received RIPng routes */
789 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
790 list = rp->info;
791 if (list == NULL)
792 continue;
793
794 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
795 if (!ripng_route_rte(rinfo))
796 continue;
797
798 if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
799 ripng_zebra_ipv6_delete(rp);
800 break;
801 }
802
803 if (rinfo) {
804 RIPNG_TIMER_OFF(rinfo->t_timeout);
805 RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
806 listnode_delete(list, rinfo);
807 ripng_info_free(rinfo);
808 }
809
810 if (list_isempty(list)) {
811 list_delete(&list);
812 rp->info = NULL;
813 agg_unlock_node(rp);
814 }
815 }
816
817 return NB_OK;
818 }
819
820 /*
821 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
822 */
823 static int
824 lib_interface_ripng_split_horizon_modify(enum nb_event event,
825 const struct lyd_node *dnode,
826 union nb_resource *resource)
827 {
828 struct interface *ifp;
829 struct ripng_interface *ri;
830
831 if (event != NB_EV_APPLY)
832 return NB_OK;
833
834 ifp = yang_dnode_get_entry(dnode, true);
835 ri = ifp->info;
836 ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
837
838 return NB_OK;
839 }
840
841 /* clang-format off */
842 const struct frr_yang_module_info frr_ripngd_info = {
843 .name = "frr-ripngd",
844 .nodes = {
845 {
846 .xpath = "/frr-ripngd:ripngd/instance",
847 .cbs.create = ripngd_instance_create,
848 .cbs.delete = ripngd_instance_delete,
849 .cbs.cli_show = cli_show_router_ripng,
850 },
851 {
852 .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
853 .cbs.modify = ripngd_instance_allow_ecmp_modify,
854 .cbs.cli_show = cli_show_ripng_allow_ecmp,
855 },
856 {
857 .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
858 .cbs.modify = ripngd_instance_default_information_originate_modify,
859 .cbs.cli_show = cli_show_ripng_default_information_originate,
860 },
861 {
862 .xpath = "/frr-ripngd:ripngd/instance/default-metric",
863 .cbs.modify = ripngd_instance_default_metric_modify,
864 .cbs.cli_show = cli_show_ripng_default_metric,
865 },
866 {
867 .xpath = "/frr-ripngd:ripngd/instance/network",
868 .cbs.create = ripngd_instance_network_create,
869 .cbs.delete = ripngd_instance_network_delete,
870 .cbs.cli_show = cli_show_ripng_network_prefix,
871 },
872 {
873 .xpath = "/frr-ripngd:ripngd/instance/interface",
874 .cbs.create = ripngd_instance_interface_create,
875 .cbs.delete = ripngd_instance_interface_delete,
876 .cbs.cli_show = cli_show_ripng_network_interface,
877 },
878 {
879 .xpath = "/frr-ripngd:ripngd/instance/offset-list",
880 .cbs.create = ripngd_instance_offset_list_create,
881 .cbs.delete = ripngd_instance_offset_list_delete,
882 .cbs.cli_show = cli_show_ripng_offset_list,
883 },
884 {
885 .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list",
886 .cbs.modify = ripngd_instance_offset_list_access_list_modify,
887 },
888 {
889 .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric",
890 .cbs.modify = ripngd_instance_offset_list_metric_modify,
891 },
892 {
893 .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
894 .cbs.create = ripngd_instance_passive_interface_create,
895 .cbs.delete = ripngd_instance_passive_interface_delete,
896 .cbs.cli_show = cli_show_ripng_passive_interface,
897 },
898 {
899 .xpath = "/frr-ripngd:ripngd/instance/redistribute",
900 .cbs.create = ripngd_instance_redistribute_create,
901 .cbs.delete = ripngd_instance_redistribute_delete,
902 .cbs.apply_finish = ripngd_instance_redistribute_apply_finish,
903 .cbs.cli_show = cli_show_ripng_redistribute,
904 },
905 {
906 .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
907 .cbs.modify = ripngd_instance_redistribute_route_map_modify,
908 .cbs.delete = ripngd_instance_redistribute_route_map_delete,
909 },
910 {
911 .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
912 .cbs.modify = ripngd_instance_redistribute_metric_modify,
913 .cbs.delete = ripngd_instance_redistribute_metric_delete,
914 },
915 {
916 .xpath = "/frr-ripngd:ripngd/instance/static-route",
917 .cbs.create = ripngd_instance_static_route_create,
918 .cbs.delete = ripngd_instance_static_route_delete,
919 .cbs.cli_show = cli_show_ripng_route,
920 },
921 {
922 .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
923 .cbs.create = ripngd_instance_aggregate_address_create,
924 .cbs.delete = ripngd_instance_aggregate_address_delete,
925 .cbs.cli_show = cli_show_ripng_aggregate_address,
926 },
927 {
928 .xpath = "/frr-ripngd:ripngd/instance/timers",
929 .cbs.apply_finish = ripngd_instance_timers_apply_finish,
930 .cbs.cli_show = cli_show_ripng_timers,
931 },
932 {
933 .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval",
934 .cbs.modify = ripngd_instance_timers_flush_interval_modify,
935 },
936 {
937 .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval",
938 .cbs.modify = ripngd_instance_timers_holddown_interval_modify,
939 },
940 {
941 .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval",
942 .cbs.modify = ripngd_instance_timers_update_interval_modify,
943 },
944 {
945 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor",
946 .cbs.get_next = ripngd_state_neighbors_neighbor_get_next,
947 .cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys,
948 .cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry,
949 },
950 {
951 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address",
952 .cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem,
953 },
954 {
955 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update",
956 .cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem,
957 },
958 {
959 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd",
960 .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
961 },
962 {
963 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd",
964 .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
965 },
966 {
967 .xpath = "/frr-ripngd:ripngd/state/routes/route",
968 .cbs.get_next = ripngd_state_routes_route_get_next,
969 .cbs.get_keys = ripngd_state_routes_route_get_keys,
970 .cbs.lookup_entry = ripngd_state_routes_route_lookup_entry,
971 },
972 {
973 .xpath = "/frr-ripngd:ripngd/state/routes/route/prefix",
974 .cbs.get_elem = ripngd_state_routes_route_prefix_get_elem,
975 },
976 {
977 .xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop",
978 .cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem,
979 },
980 {
981 .xpath = "/frr-ripngd:ripngd/state/routes/route/interface",
982 .cbs.get_elem = ripngd_state_routes_route_interface_get_elem,
983 },
984 {
985 .xpath = "/frr-ripngd:ripngd/state/routes/route/metric",
986 .cbs.get_elem = ripngd_state_routes_route_metric_get_elem,
987 },
988 {
989 .xpath = "/frr-ripngd:clear-ripng-route",
990 .cbs.rpc = clear_ripng_route_rpc,
991 },
992 {
993 .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
994 .cbs.modify = lib_interface_ripng_split_horizon_modify,
995 .cbs.cli_show = cli_show_ipv6_ripng_split_horizon,
996 },
997 {
998 .xpath = NULL,
999 },
1000 }
1001 };