]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_northbound.c
ripngd: retrofit the 'passive-interface' command to the new northbound model
[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 "northbound.h"
31 #include "libfrr.h"
32
33 #include "ripngd/ripngd.h"
34 #include "ripngd/ripng_cli.h"
35
36 /*
37 * XPath: /frr-ripngd:ripngd/instance
38 */
39 static int ripngd_instance_create(enum nb_event event,
40 const struct lyd_node *dnode,
41 union nb_resource *resource)
42 {
43 int socket;
44
45 switch (event) {
46 case NB_EV_VALIDATE:
47 break;
48 case NB_EV_PREPARE:
49 socket = ripng_make_socket();
50 if (socket < 0)
51 return NB_ERR_RESOURCE;
52 resource->fd = socket;
53 break;
54 case NB_EV_ABORT:
55 socket = resource->fd;
56 close(socket);
57 break;
58 case NB_EV_APPLY:
59 socket = resource->fd;
60 ripng_create(socket);
61 break;
62 }
63
64 return NB_OK;
65 }
66
67 static int ripngd_instance_delete(enum nb_event event,
68 const struct lyd_node *dnode)
69 {
70 if (event != NB_EV_APPLY)
71 return NB_OK;
72
73 ripng_clean();
74
75 return NB_OK;
76 }
77
78 /*
79 * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
80 */
81 static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
82 const struct lyd_node *dnode,
83 union nb_resource *resource)
84 {
85 if (event != NB_EV_APPLY)
86 return NB_OK;
87
88 ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
89 if (!ripng->ecmp)
90 ripng_ecmp_disable();
91
92 return NB_OK;
93 }
94
95 /*
96 * XPath: /frr-ripngd:ripngd/instance/default-information-originate
97 */
98 static int ripngd_instance_default_information_originate_modify(
99 enum nb_event event, const struct lyd_node *dnode,
100 union nb_resource *resource)
101 {
102 bool default_information;
103 struct prefix_ipv6 p;
104
105 if (event != NB_EV_APPLY)
106 return NB_OK;
107
108 default_information = yang_dnode_get_bool(dnode, NULL);
109 str2prefix_ipv6("::/0", &p);
110 if (default_information) {
111 ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT,
112 &p, 0, NULL, 0);
113 } else {
114 ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG,
115 RIPNG_ROUTE_DEFAULT, &p, 0);
116 }
117
118 return NB_OK;
119 }
120
121 /*
122 * XPath: /frr-ripngd:ripngd/instance/default-metric
123 */
124 static int ripngd_instance_default_metric_modify(enum nb_event event,
125 const struct lyd_node *dnode,
126 union nb_resource *resource)
127 {
128 if (event != NB_EV_APPLY)
129 return NB_OK;
130
131 ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
132
133 return NB_OK;
134 }
135
136 /*
137 * XPath: /frr-ripngd:ripngd/instance/network
138 */
139 static int ripngd_instance_network_create(enum nb_event event,
140 const struct lyd_node *dnode,
141 union nb_resource *resource)
142 {
143 struct prefix p;
144
145 if (event != NB_EV_APPLY)
146 return NB_OK;
147
148 yang_dnode_get_ipv6p(&p, dnode, NULL);
149 apply_mask_ipv6((struct prefix_ipv6 *)&p);
150
151 return ripng_enable_network_add(&p);
152 }
153
154 static int ripngd_instance_network_delete(enum nb_event event,
155 const struct lyd_node *dnode)
156 {
157 struct prefix p;
158
159 if (event != NB_EV_APPLY)
160 return NB_OK;
161
162 yang_dnode_get_ipv6p(&p, dnode, NULL);
163 apply_mask_ipv6((struct prefix_ipv6 *)&p);
164
165 return ripng_enable_network_delete(&p);
166 }
167
168 /*
169 * XPath: /frr-ripngd:ripngd/instance/interface
170 */
171 static int ripngd_instance_interface_create(enum nb_event event,
172 const struct lyd_node *dnode,
173 union nb_resource *resource)
174 {
175 const char *ifname;
176
177 if (event != NB_EV_APPLY)
178 return NB_OK;
179
180 ifname = yang_dnode_get_string(dnode, NULL);
181
182 return ripng_enable_if_add(ifname);
183 }
184
185 static int ripngd_instance_interface_delete(enum nb_event event,
186 const struct lyd_node *dnode)
187 {
188 const char *ifname;
189
190 if (event != NB_EV_APPLY)
191 return NB_OK;
192
193 ifname = yang_dnode_get_string(dnode, NULL);
194
195 return ripng_enable_if_delete(ifname);
196 }
197
198 /*
199 * XPath: /frr-ripngd:ripngd/instance/offset-list
200 */
201 static int ripngd_instance_offset_list_create(enum nb_event event,
202 const struct lyd_node *dnode,
203 union nb_resource *resource)
204 {
205 const char *ifname;
206 struct ripng_offset_list *offset;
207
208 if (event != NB_EV_APPLY)
209 return NB_OK;
210
211 ifname = yang_dnode_get_string(dnode, "./interface");
212
213 offset = ripng_offset_list_new(ifname);
214 yang_dnode_set_entry(dnode, offset);
215
216 return NB_OK;
217 }
218
219 static int ripngd_instance_offset_list_delete(enum nb_event event,
220 const struct lyd_node *dnode)
221 {
222 int direct;
223 struct ripng_offset_list *offset;
224
225 if (event != NB_EV_APPLY)
226 return NB_OK;
227
228 direct = yang_dnode_get_enum(dnode, "./direction");
229
230 offset = yang_dnode_get_entry(dnode, true);
231 if (offset->direct[direct].alist_name) {
232 free(offset->direct[direct].alist_name);
233 offset->direct[direct].alist_name = NULL;
234 }
235 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
236 && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
237 ripng_offset_list_del(offset);
238
239 return NB_OK;
240 }
241
242 /*
243 * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
244 */
245 static int
246 ripngd_instance_offset_list_access_list_modify(enum nb_event event,
247 const struct lyd_node *dnode,
248 union nb_resource *resource)
249 {
250 int direct;
251 struct ripng_offset_list *offset;
252 const char *alist_name;
253
254 if (event != NB_EV_APPLY)
255 return NB_OK;
256
257 direct = yang_dnode_get_enum(dnode, "../direction");
258 alist_name = yang_dnode_get_string(dnode, NULL);
259
260 offset = yang_dnode_get_entry(dnode, true);
261 if (offset->direct[direct].alist_name)
262 free(offset->direct[direct].alist_name);
263 offset->direct[direct].alist_name = strdup(alist_name);
264
265 return NB_OK;
266 }
267
268 /*
269 * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
270 */
271 static int
272 ripngd_instance_offset_list_metric_modify(enum nb_event event,
273 const struct lyd_node *dnode,
274 union nb_resource *resource)
275 {
276 int direct;
277 uint8_t metric;
278 struct ripng_offset_list *offset;
279
280 if (event != NB_EV_APPLY)
281 return NB_OK;
282
283 direct = yang_dnode_get_enum(dnode, "../direction");
284 metric = yang_dnode_get_uint8(dnode, NULL);
285
286 offset = yang_dnode_get_entry(dnode, true);
287 offset->direct[direct].metric = metric;
288
289 return NB_OK;
290 }
291
292 /*
293 * XPath: /frr-ripngd:ripngd/instance/passive-interface
294 */
295 static int
296 ripngd_instance_passive_interface_create(enum nb_event event,
297 const struct lyd_node *dnode,
298 union nb_resource *resource)
299 {
300 const char *ifname;
301
302 if (event != NB_EV_APPLY)
303 return NB_OK;
304
305 ifname = yang_dnode_get_string(dnode, NULL);
306
307 return ripng_passive_interface_set(ifname);
308 }
309
310 static int
311 ripngd_instance_passive_interface_delete(enum nb_event event,
312 const struct lyd_node *dnode)
313 {
314 const char *ifname;
315
316 if (event != NB_EV_APPLY)
317 return NB_OK;
318
319 ifname = yang_dnode_get_string(dnode, NULL);
320
321 return ripng_passive_interface_unset(ifname);
322 }
323
324 /*
325 * XPath: /frr-ripngd:ripngd/instance/redistribute
326 */
327 static int ripngd_instance_redistribute_create(enum nb_event event,
328 const struct lyd_node *dnode,
329 union nb_resource *resource)
330 {
331 /* TODO: implement me. */
332 return NB_OK;
333 }
334
335 static int ripngd_instance_redistribute_delete(enum nb_event event,
336 const struct lyd_node *dnode)
337 {
338 /* TODO: implement me. */
339 return NB_OK;
340 }
341
342 /*
343 * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
344 */
345 static int
346 ripngd_instance_redistribute_route_map_modify(enum nb_event event,
347 const struct lyd_node *dnode,
348 union nb_resource *resource)
349 {
350 /* TODO: implement me. */
351 return NB_OK;
352 }
353
354 static int
355 ripngd_instance_redistribute_route_map_delete(enum nb_event event,
356 const struct lyd_node *dnode)
357 {
358 /* TODO: implement me. */
359 return NB_OK;
360 }
361
362 /*
363 * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
364 */
365 static int
366 ripngd_instance_redistribute_metric_modify(enum nb_event event,
367 const struct lyd_node *dnode,
368 union nb_resource *resource)
369 {
370 /* TODO: implement me. */
371 return NB_OK;
372 }
373
374 static int
375 ripngd_instance_redistribute_metric_delete(enum nb_event event,
376 const struct lyd_node *dnode)
377 {
378 /* TODO: implement me. */
379 return NB_OK;
380 }
381
382 /*
383 * XPath: /frr-ripngd:ripngd/instance/static-route
384 */
385 static int ripngd_instance_static_route_create(enum nb_event event,
386 const struct lyd_node *dnode,
387 union nb_resource *resource)
388 {
389 /* TODO: implement me. */
390 return NB_OK;
391 }
392
393 static int ripngd_instance_static_route_delete(enum nb_event event,
394 const struct lyd_node *dnode)
395 {
396 /* TODO: implement me. */
397 return NB_OK;
398 }
399
400 /*
401 * XPath: /frr-ripngd:ripngd/instance/aggregate-address
402 */
403 static int
404 ripngd_instance_aggregate_address_create(enum nb_event event,
405 const struct lyd_node *dnode,
406 union nb_resource *resource)
407 {
408 /* TODO: implement me. */
409 return NB_OK;
410 }
411
412 static int
413 ripngd_instance_aggregate_address_delete(enum nb_event event,
414 const struct lyd_node *dnode)
415 {
416 /* TODO: implement me. */
417 return NB_OK;
418 }
419
420 /*
421 * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
422 */
423 static int
424 ripngd_instance_timers_flush_interval_modify(enum nb_event event,
425 const struct lyd_node *dnode,
426 union nb_resource *resource)
427 {
428 /* TODO: implement me. */
429 return NB_OK;
430 }
431
432 /*
433 * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
434 */
435 static int
436 ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
437 const struct lyd_node *dnode,
438 union nb_resource *resource)
439 {
440 /* TODO: implement me. */
441 return NB_OK;
442 }
443
444 /*
445 * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
446 */
447 static int
448 ripngd_instance_timers_update_interval_modify(enum nb_event event,
449 const struct lyd_node *dnode,
450 union nb_resource *resource)
451 {
452 /* TODO: implement me. */
453 return NB_OK;
454 }
455
456 /*
457 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor
458 */
459 static const void *
460 ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
461 const void *list_entry)
462 {
463 /* TODO: implement me. */
464 return NULL;
465 }
466
467 static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
468 struct yang_list_keys *keys)
469 {
470 /* TODO: implement me. */
471 return NB_OK;
472 }
473
474 static const void *
475 ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
476 const struct yang_list_keys *keys)
477 {
478 /* TODO: implement me. */
479 return NULL;
480 }
481
482 /*
483 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/address
484 */
485 static struct yang_data *
486 ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath,
487 const void *list_entry)
488 {
489 /* TODO: implement me. */
490 return NULL;
491 }
492
493 /*
494 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/last-update
495 */
496 static struct yang_data *
497 ripngd_state_neighbors_neighbor_last_update_get_elem(const char *xpath,
498 const void *list_entry)
499 {
500 /* TODO: implement me. */
501 return NULL;
502 }
503
504 /*
505 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd
506 */
507 static struct yang_data *
508 ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
509 const char *xpath, const void *list_entry)
510 {
511 /* TODO: implement me. */
512 return NULL;
513 }
514
515 /*
516 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd
517 */
518 static struct yang_data *
519 ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
520 const void *list_entry)
521 {
522 /* TODO: implement me. */
523 return NULL;
524 }
525
526 /*
527 * XPath: /frr-ripngd:ripngd/state/routes/route
528 */
529 static const void *
530 ripngd_state_routes_route_get_next(const void *parent_list_entry,
531 const void *list_entry)
532 {
533 /* TODO: implement me. */
534 return NULL;
535 }
536
537 static int ripngd_state_routes_route_get_keys(const void *list_entry,
538 struct yang_list_keys *keys)
539 {
540 /* TODO: implement me. */
541 return NB_OK;
542 }
543
544 static const void *
545 ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
546 const struct yang_list_keys *keys)
547 {
548 /* TODO: implement me. */
549 return NULL;
550 }
551
552 /*
553 * XPath: /frr-ripngd:ripngd/state/routes/route/prefix
554 */
555 static struct yang_data *
556 ripngd_state_routes_route_prefix_get_elem(const char *xpath,
557 const void *list_entry)
558 {
559 /* TODO: implement me. */
560 return NULL;
561 }
562
563 /*
564 * XPath: /frr-ripngd:ripngd/state/routes/route/next-hop
565 */
566 static struct yang_data *
567 ripngd_state_routes_route_next_hop_get_elem(const char *xpath,
568 const void *list_entry)
569 {
570 /* TODO: implement me. */
571 return NULL;
572 }
573
574 /*
575 * XPath: /frr-ripngd:ripngd/state/routes/route/interface
576 */
577 static struct yang_data *
578 ripngd_state_routes_route_interface_get_elem(const char *xpath,
579 const void *list_entry)
580 {
581 /* TODO: implement me. */
582 return NULL;
583 }
584
585 /*
586 * XPath: /frr-ripngd:ripngd/state/routes/route/metric
587 */
588 static struct yang_data *
589 ripngd_state_routes_route_metric_get_elem(const char *xpath,
590 const void *list_entry)
591 {
592 /* TODO: implement me. */
593 return NULL;
594 }
595
596 /*
597 * XPath: /frr-ripngd:clear-ripng-route
598 */
599 static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
600 struct list *output)
601 {
602 /* TODO: implement me. */
603 return NB_OK;
604 }
605
606 /*
607 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
608 */
609 static int
610 lib_interface_ripng_split_horizon_modify(enum nb_event event,
611 const struct lyd_node *dnode,
612 union nb_resource *resource)
613 {
614 /* TODO: implement me. */
615 return NB_OK;
616 }
617
618 /* clang-format off */
619 const struct frr_yang_module_info frr_ripngd_info = {
620 .name = "frr-ripngd",
621 .nodes = {
622 {
623 .xpath = "/frr-ripngd:ripngd/instance",
624 .cbs.create = ripngd_instance_create,
625 .cbs.delete = ripngd_instance_delete,
626 .cbs.cli_show = cli_show_router_ripng,
627 },
628 {
629 .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
630 .cbs.modify = ripngd_instance_allow_ecmp_modify,
631 .cbs.cli_show = cli_show_ripng_allow_ecmp,
632 },
633 {
634 .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
635 .cbs.modify = ripngd_instance_default_information_originate_modify,
636 .cbs.cli_show = cli_show_ripng_default_information_originate,
637 },
638 {
639 .xpath = "/frr-ripngd:ripngd/instance/default-metric",
640 .cbs.modify = ripngd_instance_default_metric_modify,
641 .cbs.cli_show = cli_show_ripng_default_metric,
642 },
643 {
644 .xpath = "/frr-ripngd:ripngd/instance/network",
645 .cbs.create = ripngd_instance_network_create,
646 .cbs.delete = ripngd_instance_network_delete,
647 .cbs.cli_show = cli_show_ripng_network_prefix,
648 },
649 {
650 .xpath = "/frr-ripngd:ripngd/instance/interface",
651 .cbs.create = ripngd_instance_interface_create,
652 .cbs.delete = ripngd_instance_interface_delete,
653 .cbs.cli_show = cli_show_ripng_network_interface,
654 },
655 {
656 .xpath = "/frr-ripngd:ripngd/instance/offset-list",
657 .cbs.create = ripngd_instance_offset_list_create,
658 .cbs.delete = ripngd_instance_offset_list_delete,
659 .cbs.cli_show = cli_show_ripng_offset_list,
660 },
661 {
662 .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list",
663 .cbs.modify = ripngd_instance_offset_list_access_list_modify,
664 },
665 {
666 .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric",
667 .cbs.modify = ripngd_instance_offset_list_metric_modify,
668 },
669 {
670 .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
671 .cbs.create = ripngd_instance_passive_interface_create,
672 .cbs.delete = ripngd_instance_passive_interface_delete,
673 .cbs.cli_show = cli_show_ripng_passive_interface,
674 },
675 {
676 .xpath = "/frr-ripngd:ripngd/instance/redistribute",
677 .cbs.create = ripngd_instance_redistribute_create,
678 .cbs.delete = ripngd_instance_redistribute_delete,
679 },
680 {
681 .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
682 .cbs.modify = ripngd_instance_redistribute_route_map_modify,
683 .cbs.delete = ripngd_instance_redistribute_route_map_delete,
684 },
685 {
686 .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
687 .cbs.modify = ripngd_instance_redistribute_metric_modify,
688 .cbs.delete = ripngd_instance_redistribute_metric_delete,
689 },
690 {
691 .xpath = "/frr-ripngd:ripngd/instance/static-route",
692 .cbs.create = ripngd_instance_static_route_create,
693 .cbs.delete = ripngd_instance_static_route_delete,
694 },
695 {
696 .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
697 .cbs.create = ripngd_instance_aggregate_address_create,
698 .cbs.delete = ripngd_instance_aggregate_address_delete,
699 },
700 {
701 .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval",
702 .cbs.modify = ripngd_instance_timers_flush_interval_modify,
703 },
704 {
705 .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval",
706 .cbs.modify = ripngd_instance_timers_holddown_interval_modify,
707 },
708 {
709 .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval",
710 .cbs.modify = ripngd_instance_timers_update_interval_modify,
711 },
712 {
713 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor",
714 .cbs.get_next = ripngd_state_neighbors_neighbor_get_next,
715 .cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys,
716 .cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry,
717 },
718 {
719 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address",
720 .cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem,
721 },
722 {
723 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update",
724 .cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem,
725 },
726 {
727 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd",
728 .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
729 },
730 {
731 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd",
732 .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
733 },
734 {
735 .xpath = "/frr-ripngd:ripngd/state/routes/route",
736 .cbs.get_next = ripngd_state_routes_route_get_next,
737 .cbs.get_keys = ripngd_state_routes_route_get_keys,
738 .cbs.lookup_entry = ripngd_state_routes_route_lookup_entry,
739 },
740 {
741 .xpath = "/frr-ripngd:ripngd/state/routes/route/prefix",
742 .cbs.get_elem = ripngd_state_routes_route_prefix_get_elem,
743 },
744 {
745 .xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop",
746 .cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem,
747 },
748 {
749 .xpath = "/frr-ripngd:ripngd/state/routes/route/interface",
750 .cbs.get_elem = ripngd_state_routes_route_interface_get_elem,
751 },
752 {
753 .xpath = "/frr-ripngd:ripngd/state/routes/route/metric",
754 .cbs.get_elem = ripngd_state_routes_route_metric_get_elem,
755 },
756 {
757 .xpath = "/frr-ripngd:clear-ripng-route",
758 .cbs.rpc = clear_ripng_route_rpc,
759 },
760 {
761 .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
762 .cbs.modify = lib_interface_ripng_split_horizon_modify,
763 },
764 {
765 .xpath = NULL,
766 },
767 }
768 };