]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_northbound.c
ripngd: implement the 'clear-ripng-route' YANG RPC
[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 /* TODO: implement me. */
583 return NULL;
584 }
585
586 static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
587 struct yang_list_keys *keys)
588 {
589 /* TODO: implement me. */
590 return NB_OK;
591 }
592
593 static const void *
594 ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
595 const struct yang_list_keys *keys)
596 {
597 /* TODO: implement me. */
598 return NULL;
599 }
600
601 /*
602 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/address
603 */
604 static struct yang_data *
605 ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath,
606 const void *list_entry)
607 {
608 /* TODO: implement me. */
609 return NULL;
610 }
611
612 /*
613 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/last-update
614 */
615 static struct yang_data *
616 ripngd_state_neighbors_neighbor_last_update_get_elem(const char *xpath,
617 const void *list_entry)
618 {
619 /* TODO: implement me. */
620 return NULL;
621 }
622
623 /*
624 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd
625 */
626 static struct yang_data *
627 ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
628 const char *xpath, const void *list_entry)
629 {
630 /* TODO: implement me. */
631 return NULL;
632 }
633
634 /*
635 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd
636 */
637 static struct yang_data *
638 ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
639 const void *list_entry)
640 {
641 /* TODO: implement me. */
642 return NULL;
643 }
644
645 /*
646 * XPath: /frr-ripngd:ripngd/state/routes/route
647 */
648 static const void *
649 ripngd_state_routes_route_get_next(const void *parent_list_entry,
650 const void *list_entry)
651 {
652 /* TODO: implement me. */
653 return NULL;
654 }
655
656 static int ripngd_state_routes_route_get_keys(const void *list_entry,
657 struct yang_list_keys *keys)
658 {
659 /* TODO: implement me. */
660 return NB_OK;
661 }
662
663 static const void *
664 ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
665 const struct yang_list_keys *keys)
666 {
667 /* TODO: implement me. */
668 return NULL;
669 }
670
671 /*
672 * XPath: /frr-ripngd:ripngd/state/routes/route/prefix
673 */
674 static struct yang_data *
675 ripngd_state_routes_route_prefix_get_elem(const char *xpath,
676 const void *list_entry)
677 {
678 /* TODO: implement me. */
679 return NULL;
680 }
681
682 /*
683 * XPath: /frr-ripngd:ripngd/state/routes/route/next-hop
684 */
685 static struct yang_data *
686 ripngd_state_routes_route_next_hop_get_elem(const char *xpath,
687 const void *list_entry)
688 {
689 /* TODO: implement me. */
690 return NULL;
691 }
692
693 /*
694 * XPath: /frr-ripngd:ripngd/state/routes/route/interface
695 */
696 static struct yang_data *
697 ripngd_state_routes_route_interface_get_elem(const char *xpath,
698 const void *list_entry)
699 {
700 /* TODO: implement me. */
701 return NULL;
702 }
703
704 /*
705 * XPath: /frr-ripngd:ripngd/state/routes/route/metric
706 */
707 static struct yang_data *
708 ripngd_state_routes_route_metric_get_elem(const char *xpath,
709 const void *list_entry)
710 {
711 /* TODO: implement me. */
712 return NULL;
713 }
714
715 /*
716 * XPath: /frr-ripngd:clear-ripng-route
717 */
718 static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
719 struct list *output)
720 {
721 struct agg_node *rp;
722 struct ripng_info *rinfo;
723 struct list *list;
724 struct listnode *listnode;
725
726 /* Clear received RIPng routes */
727 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
728 list = rp->info;
729 if (list == NULL)
730 continue;
731
732 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
733 if (!ripng_route_rte(rinfo))
734 continue;
735
736 if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
737 ripng_zebra_ipv6_delete(rp);
738 break;
739 }
740
741 if (rinfo) {
742 RIPNG_TIMER_OFF(rinfo->t_timeout);
743 RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
744 listnode_delete(list, rinfo);
745 ripng_info_free(rinfo);
746 }
747
748 if (list_isempty(list)) {
749 list_delete(&list);
750 rp->info = NULL;
751 agg_unlock_node(rp);
752 }
753 }
754
755 return NB_OK;
756 }
757
758 /*
759 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
760 */
761 static int
762 lib_interface_ripng_split_horizon_modify(enum nb_event event,
763 const struct lyd_node *dnode,
764 union nb_resource *resource)
765 {
766 struct interface *ifp;
767 struct ripng_interface *ri;
768
769 if (event != NB_EV_APPLY)
770 return NB_OK;
771
772 ifp = yang_dnode_get_entry(dnode, true);
773 ri = ifp->info;
774 ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
775
776 return NB_OK;
777 }
778
779 /* clang-format off */
780 const struct frr_yang_module_info frr_ripngd_info = {
781 .name = "frr-ripngd",
782 .nodes = {
783 {
784 .xpath = "/frr-ripngd:ripngd/instance",
785 .cbs.create = ripngd_instance_create,
786 .cbs.delete = ripngd_instance_delete,
787 .cbs.cli_show = cli_show_router_ripng,
788 },
789 {
790 .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
791 .cbs.modify = ripngd_instance_allow_ecmp_modify,
792 .cbs.cli_show = cli_show_ripng_allow_ecmp,
793 },
794 {
795 .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
796 .cbs.modify = ripngd_instance_default_information_originate_modify,
797 .cbs.cli_show = cli_show_ripng_default_information_originate,
798 },
799 {
800 .xpath = "/frr-ripngd:ripngd/instance/default-metric",
801 .cbs.modify = ripngd_instance_default_metric_modify,
802 .cbs.cli_show = cli_show_ripng_default_metric,
803 },
804 {
805 .xpath = "/frr-ripngd:ripngd/instance/network",
806 .cbs.create = ripngd_instance_network_create,
807 .cbs.delete = ripngd_instance_network_delete,
808 .cbs.cli_show = cli_show_ripng_network_prefix,
809 },
810 {
811 .xpath = "/frr-ripngd:ripngd/instance/interface",
812 .cbs.create = ripngd_instance_interface_create,
813 .cbs.delete = ripngd_instance_interface_delete,
814 .cbs.cli_show = cli_show_ripng_network_interface,
815 },
816 {
817 .xpath = "/frr-ripngd:ripngd/instance/offset-list",
818 .cbs.create = ripngd_instance_offset_list_create,
819 .cbs.delete = ripngd_instance_offset_list_delete,
820 .cbs.cli_show = cli_show_ripng_offset_list,
821 },
822 {
823 .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list",
824 .cbs.modify = ripngd_instance_offset_list_access_list_modify,
825 },
826 {
827 .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric",
828 .cbs.modify = ripngd_instance_offset_list_metric_modify,
829 },
830 {
831 .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
832 .cbs.create = ripngd_instance_passive_interface_create,
833 .cbs.delete = ripngd_instance_passive_interface_delete,
834 .cbs.cli_show = cli_show_ripng_passive_interface,
835 },
836 {
837 .xpath = "/frr-ripngd:ripngd/instance/redistribute",
838 .cbs.create = ripngd_instance_redistribute_create,
839 .cbs.delete = ripngd_instance_redistribute_delete,
840 .cbs.apply_finish = ripngd_instance_redistribute_apply_finish,
841 .cbs.cli_show = cli_show_ripng_redistribute,
842 },
843 {
844 .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
845 .cbs.modify = ripngd_instance_redistribute_route_map_modify,
846 .cbs.delete = ripngd_instance_redistribute_route_map_delete,
847 },
848 {
849 .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
850 .cbs.modify = ripngd_instance_redistribute_metric_modify,
851 .cbs.delete = ripngd_instance_redistribute_metric_delete,
852 },
853 {
854 .xpath = "/frr-ripngd:ripngd/instance/static-route",
855 .cbs.create = ripngd_instance_static_route_create,
856 .cbs.delete = ripngd_instance_static_route_delete,
857 .cbs.cli_show = cli_show_ripng_route,
858 },
859 {
860 .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
861 .cbs.create = ripngd_instance_aggregate_address_create,
862 .cbs.delete = ripngd_instance_aggregate_address_delete,
863 .cbs.cli_show = cli_show_ripng_aggregate_address,
864 },
865 {
866 .xpath = "/frr-ripngd:ripngd/instance/timers",
867 .cbs.apply_finish = ripngd_instance_timers_apply_finish,
868 .cbs.cli_show = cli_show_ripng_timers,
869 },
870 {
871 .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval",
872 .cbs.modify = ripngd_instance_timers_flush_interval_modify,
873 },
874 {
875 .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval",
876 .cbs.modify = ripngd_instance_timers_holddown_interval_modify,
877 },
878 {
879 .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval",
880 .cbs.modify = ripngd_instance_timers_update_interval_modify,
881 },
882 {
883 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor",
884 .cbs.get_next = ripngd_state_neighbors_neighbor_get_next,
885 .cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys,
886 .cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry,
887 },
888 {
889 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address",
890 .cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem,
891 },
892 {
893 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update",
894 .cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem,
895 },
896 {
897 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd",
898 .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
899 },
900 {
901 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd",
902 .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
903 },
904 {
905 .xpath = "/frr-ripngd:ripngd/state/routes/route",
906 .cbs.get_next = ripngd_state_routes_route_get_next,
907 .cbs.get_keys = ripngd_state_routes_route_get_keys,
908 .cbs.lookup_entry = ripngd_state_routes_route_lookup_entry,
909 },
910 {
911 .xpath = "/frr-ripngd:ripngd/state/routes/route/prefix",
912 .cbs.get_elem = ripngd_state_routes_route_prefix_get_elem,
913 },
914 {
915 .xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop",
916 .cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem,
917 },
918 {
919 .xpath = "/frr-ripngd:ripngd/state/routes/route/interface",
920 .cbs.get_elem = ripngd_state_routes_route_interface_get_elem,
921 },
922 {
923 .xpath = "/frr-ripngd:ripngd/state/routes/route/metric",
924 .cbs.get_elem = ripngd_state_routes_route_metric_get_elem,
925 },
926 {
927 .xpath = "/frr-ripngd:clear-ripng-route",
928 .cbs.rpc = clear_ripng_route_rpc,
929 },
930 {
931 .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
932 .cbs.modify = lib_interface_ripng_split_horizon_modify,
933 .cbs.cli_show = cli_show_ipv6_ripng_split_horizon,
934 },
935 {
936 .xpath = NULL,
937 },
938 }
939 };