]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_northbound.c
ripd: make YANG operational-data VRF aware too
[mirror_frr.git] / ripd / rip_northbound.c
1 /*
2 * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
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 "ripd/ripd.h"
34 #include "ripd/rip_cli.h"
35
36 /*
37 * XPath: /frr-ripd:ripd/instance
38 */
39 static int ripd_instance_create(enum nb_event event,
40 const struct lyd_node *dnode,
41 union nb_resource *resource)
42 {
43 struct rip *rip;
44 struct vrf *vrf;
45 const char *vrf_name;
46 int socket;
47
48 vrf_name = yang_dnode_get_string(dnode, "./vrf");
49 vrf = vrf_lookup_by_name(vrf_name);
50
51 /*
52 * Try to create a RIP socket only if the VRF is enabled, otherwise
53 * create a disabled RIP instance and wait for the VRF to be enabled.
54 */
55 switch (event) {
56 case NB_EV_VALIDATE:
57 break;
58 case NB_EV_PREPARE:
59 if (!vrf || !vrf_is_enabled(vrf))
60 break;
61
62 socket = rip_create_socket(vrf);
63 if (socket < 0)
64 return NB_ERR_RESOURCE;
65 resource->fd = socket;
66 break;
67 case NB_EV_ABORT:
68 if (!vrf || !vrf_is_enabled(vrf))
69 break;
70
71 socket = resource->fd;
72 close(socket);
73 break;
74 case NB_EV_APPLY:
75 if (vrf && vrf_is_enabled(vrf))
76 socket = resource->fd;
77 else
78 socket = -1;
79
80 rip = rip_create(vrf_name, vrf, socket);
81 yang_dnode_set_entry(dnode, rip);
82 break;
83 }
84
85 return NB_OK;
86 }
87
88 static int ripd_instance_delete(enum nb_event event,
89 const struct lyd_node *dnode)
90 {
91 struct rip *rip;
92
93 if (event != NB_EV_APPLY)
94 return NB_OK;
95
96 rip = yang_dnode_get_entry(dnode, true);
97 rip_clean(rip);
98
99 return NB_OK;
100 }
101
102 static const void *ripd_instance_get_next(const void *parent_list_entry,
103 const void *list_entry)
104 {
105 const struct rip *rip = list_entry;
106
107 if (list_entry == NULL)
108 rip = RB_MIN(rip_instance_head, &rip_instances);
109 else
110 rip = RB_NEXT(rip_instance_head, (struct rip *)rip);
111
112 return rip;
113 }
114
115 static int ripd_instance_get_keys(const void *list_entry,
116 struct yang_list_keys *keys)
117 {
118 const struct rip *rip = list_entry;
119
120 keys->num = 1;
121 strlcpy(keys->key[0], rip->vrf_name, sizeof(keys->key[0]));
122
123 return NB_OK;
124 }
125
126 static const void *ripd_instance_lookup_entry(const void *parent_list_entry,
127 const struct yang_list_keys *keys)
128 {
129 const char *vrf_name = keys->key[0];
130
131 return rip_lookup_by_vrf_name(vrf_name);
132 }
133
134 /*
135 * XPath: /frr-ripd:ripd/instance/allow-ecmp
136 */
137 static int ripd_instance_allow_ecmp_modify(enum nb_event event,
138 const struct lyd_node *dnode,
139 union nb_resource *resource)
140 {
141 struct rip *rip;
142
143 if (event != NB_EV_APPLY)
144 return NB_OK;
145
146 rip = yang_dnode_get_entry(dnode, true);
147 rip->ecmp = yang_dnode_get_bool(dnode, NULL);
148 if (!rip->ecmp)
149 rip_ecmp_disable(rip);
150
151 return NB_OK;
152 }
153
154 /*
155 * XPath: /frr-ripd:ripd/instance/default-information-originate
156 */
157 static int
158 ripd_instance_default_information_originate_modify(enum nb_event event,
159 const struct lyd_node *dnode,
160 union nb_resource *resource)
161 {
162 struct rip *rip;
163 bool default_information;
164 struct prefix_ipv4 p;
165
166 if (event != NB_EV_APPLY)
167 return NB_OK;
168
169 rip = yang_dnode_get_entry(dnode, true);
170 default_information = yang_dnode_get_bool(dnode, NULL);
171
172 memset(&p, 0, sizeof(struct prefix_ipv4));
173 p.family = AF_INET;
174 if (default_information) {
175 struct nexthop nh;
176
177 memset(&nh, 0, sizeof(nh));
178 nh.type = NEXTHOP_TYPE_IPV4;
179 rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT,
180 &p, &nh, 0, 0, 0);
181 } else {
182 rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT,
183 &p, 0);
184 }
185
186 return NB_OK;
187 }
188
189 /*
190 * XPath: /frr-ripd:ripd/instance/default-metric
191 */
192 static int ripd_instance_default_metric_modify(enum nb_event event,
193 const struct lyd_node *dnode,
194 union nb_resource *resource)
195 {
196 struct rip *rip;
197
198 if (event != NB_EV_APPLY)
199 return NB_OK;
200
201 rip = yang_dnode_get_entry(dnode, true);
202 rip->default_metric = yang_dnode_get_uint8(dnode, NULL);
203 /* rip_update_default_metric (); */
204
205 return NB_OK;
206 }
207
208 /*
209 * XPath: /frr-ripd:ripd/instance/distance/default
210 */
211 static int ripd_instance_distance_default_modify(enum nb_event event,
212 const struct lyd_node *dnode,
213 union nb_resource *resource)
214 {
215 struct rip *rip;
216
217 if (event != NB_EV_APPLY)
218 return NB_OK;
219
220 rip = yang_dnode_get_entry(dnode, true);
221 rip->distance = yang_dnode_get_uint8(dnode, NULL);
222
223 return NB_OK;
224 }
225
226 /*
227 * XPath: /frr-ripd:ripd/instance/distance/source
228 */
229 static int ripd_instance_distance_source_create(enum nb_event event,
230 const struct lyd_node *dnode,
231 union nb_resource *resource)
232 {
233 struct rip *rip;
234 struct prefix_ipv4 prefix;
235 struct route_node *rn;
236
237 if (event != NB_EV_APPLY)
238 return NB_OK;
239
240 yang_dnode_get_ipv4p(&prefix, dnode, "./prefix");
241 apply_mask_ipv4(&prefix);
242
243 /* Get RIP distance node. */
244 rip = yang_dnode_get_entry(dnode, true);
245 rn = route_node_get(rip->distance_table, (struct prefix *)&prefix);
246 rn->info = rip_distance_new();
247 yang_dnode_set_entry(dnode, rn);
248
249 return NB_OK;
250 }
251
252 static int ripd_instance_distance_source_delete(enum nb_event event,
253 const struct lyd_node *dnode)
254 {
255 struct route_node *rn;
256 struct rip_distance *rdistance;
257
258 if (event != NB_EV_APPLY)
259 return NB_OK;
260
261 rn = yang_dnode_get_entry(dnode, true);
262 rdistance = rn->info;
263 rip_distance_free(rdistance);
264 rn->info = NULL;
265 route_unlock_node(rn);
266
267 return NB_OK;
268 }
269
270 /*
271 * XPath: /frr-ripd:ripd/instance/distance/source/distance
272 */
273 static int
274 ripd_instance_distance_source_distance_modify(enum nb_event event,
275 const struct lyd_node *dnode,
276 union nb_resource *resource)
277 {
278 struct route_node *rn;
279 uint8_t distance;
280 struct rip_distance *rdistance;
281
282 if (event != NB_EV_APPLY)
283 return NB_OK;
284
285 /* Set distance value. */
286 rn = yang_dnode_get_entry(dnode, true);
287 distance = yang_dnode_get_uint8(dnode, NULL);
288 rdistance = rn->info;
289 rdistance->distance = distance;
290
291 return NB_OK;
292 }
293
294 /*
295 * XPath: /frr-ripd:ripd/instance/distance/source/access-list
296 */
297 static int
298 ripd_instance_distance_source_access_list_modify(enum nb_event event,
299 const struct lyd_node *dnode,
300 union nb_resource *resource)
301 {
302 const char *acl_name;
303 struct route_node *rn;
304 struct rip_distance *rdistance;
305
306 if (event != NB_EV_APPLY)
307 return NB_OK;
308
309 acl_name = yang_dnode_get_string(dnode, NULL);
310
311 /* Set access-list */
312 rn = yang_dnode_get_entry(dnode, true);
313 rdistance = rn->info;
314 if (rdistance->access_list)
315 free(rdistance->access_list);
316 rdistance->access_list = strdup(acl_name);
317
318 return NB_OK;
319 }
320
321 static int
322 ripd_instance_distance_source_access_list_delete(enum nb_event event,
323 const struct lyd_node *dnode)
324 {
325 struct route_node *rn;
326 struct rip_distance *rdistance;
327
328 if (event != NB_EV_APPLY)
329 return NB_OK;
330
331 /* Reset access-list configuration. */
332 rn = yang_dnode_get_entry(dnode, true);
333 rdistance = rn->info;
334 free(rdistance->access_list);
335 rdistance->access_list = NULL;
336
337 return NB_OK;
338 }
339
340 /*
341 * XPath: /frr-ripd:ripd/instance/explicit-neighbor
342 */
343 static int ripd_instance_explicit_neighbor_create(enum nb_event event,
344 const struct lyd_node *dnode,
345 union nb_resource *resource)
346 {
347 struct rip *rip;
348 struct prefix_ipv4 p;
349
350 if (event != NB_EV_APPLY)
351 return NB_OK;
352
353 rip = yang_dnode_get_entry(dnode, true);
354 p.family = AF_INET;
355 p.prefixlen = IPV4_MAX_BITLEN;
356 yang_dnode_get_ipv4(&p.prefix, dnode, NULL);
357
358 return rip_neighbor_add(rip, &p);
359 }
360
361 static int ripd_instance_explicit_neighbor_delete(enum nb_event event,
362 const struct lyd_node *dnode)
363 {
364 struct rip *rip;
365 struct prefix_ipv4 p;
366
367 if (event != NB_EV_APPLY)
368 return NB_OK;
369
370 rip = yang_dnode_get_entry(dnode, true);
371 p.family = AF_INET;
372 p.prefixlen = IPV4_MAX_BITLEN;
373 yang_dnode_get_ipv4(&p.prefix, dnode, NULL);
374
375 return rip_neighbor_delete(rip, &p);
376 }
377
378 /*
379 * XPath: /frr-ripd:ripd/instance/network
380 */
381 static int ripd_instance_network_create(enum nb_event event,
382 const struct lyd_node *dnode,
383 union nb_resource *resource)
384 {
385 struct rip *rip;
386 struct prefix p;
387
388 if (event != NB_EV_APPLY)
389 return NB_OK;
390
391 rip = yang_dnode_get_entry(dnode, true);
392 yang_dnode_get_ipv4p(&p, dnode, NULL);
393 apply_mask_ipv4((struct prefix_ipv4 *)&p);
394
395 return rip_enable_network_add(rip, &p);
396 }
397
398 static int ripd_instance_network_delete(enum nb_event event,
399 const struct lyd_node *dnode)
400 {
401 struct rip *rip;
402 struct prefix p;
403
404 if (event != NB_EV_APPLY)
405 return NB_OK;
406
407 rip = yang_dnode_get_entry(dnode, true);
408 yang_dnode_get_ipv4p(&p, dnode, NULL);
409 apply_mask_ipv4((struct prefix_ipv4 *)&p);
410
411 return rip_enable_network_delete(rip, &p);
412 }
413
414 /*
415 * XPath: /frr-ripd:ripd/instance/interface
416 */
417 static int ripd_instance_interface_create(enum nb_event event,
418 const struct lyd_node *dnode,
419 union nb_resource *resource)
420 {
421 struct rip *rip;
422 const char *ifname;
423
424 if (event != NB_EV_APPLY)
425 return NB_OK;
426
427 rip = yang_dnode_get_entry(dnode, true);
428 ifname = yang_dnode_get_string(dnode, NULL);
429
430 return rip_enable_if_add(rip, ifname);
431 }
432
433 static int ripd_instance_interface_delete(enum nb_event event,
434 const struct lyd_node *dnode)
435 {
436 struct rip *rip;
437 const char *ifname;
438
439 if (event != NB_EV_APPLY)
440 return NB_OK;
441
442 rip = yang_dnode_get_entry(dnode, true);
443 ifname = yang_dnode_get_string(dnode, NULL);
444
445 return rip_enable_if_delete(rip, ifname);
446 }
447
448 /*
449 * XPath: /frr-ripd:ripd/instance/offset-list
450 */
451 static int ripd_instance_offset_list_create(enum nb_event event,
452 const struct lyd_node *dnode,
453 union nb_resource *resource)
454 {
455 struct rip *rip;
456 const char *ifname;
457 struct rip_offset_list *offset;
458
459 if (event != NB_EV_APPLY)
460 return NB_OK;
461
462 rip = yang_dnode_get_entry(dnode, true);
463 ifname = yang_dnode_get_string(dnode, "./interface");
464
465 offset = rip_offset_list_new(rip, ifname);
466 yang_dnode_set_entry(dnode, offset);
467
468 return NB_OK;
469 }
470
471 static int ripd_instance_offset_list_delete(enum nb_event event,
472 const struct lyd_node *dnode)
473 {
474 int direct;
475 struct rip_offset_list *offset;
476
477 if (event != NB_EV_APPLY)
478 return NB_OK;
479
480 direct = yang_dnode_get_enum(dnode, "./direction");
481
482 offset = yang_dnode_get_entry(dnode, true);
483 if (offset->direct[direct].alist_name) {
484 free(offset->direct[direct].alist_name);
485 offset->direct[direct].alist_name = NULL;
486 }
487 if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL
488 && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL)
489 offset_list_del(offset);
490
491 return NB_OK;
492 }
493
494 /*
495 * XPath: /frr-ripd:ripd/instance/offset-list/access-list
496 */
497 static int
498 ripd_instance_offset_list_access_list_modify(enum nb_event event,
499 const struct lyd_node *dnode,
500 union nb_resource *resource)
501 {
502 int direct;
503 struct rip_offset_list *offset;
504 const char *alist_name;
505
506 if (event != NB_EV_APPLY)
507 return NB_OK;
508
509 direct = yang_dnode_get_enum(dnode, "../direction");
510 alist_name = yang_dnode_get_string(dnode, NULL);
511
512 offset = yang_dnode_get_entry(dnode, true);
513 if (offset->direct[direct].alist_name)
514 free(offset->direct[direct].alist_name);
515 offset->direct[direct].alist_name = strdup(alist_name);
516
517 return NB_OK;
518 }
519
520 /*
521 * XPath: /frr-ripd:ripd/instance/offset-list/metric
522 */
523 static int ripd_instance_offset_list_metric_modify(enum nb_event event,
524 const struct lyd_node *dnode,
525 union nb_resource *resource)
526 {
527 int direct;
528 uint8_t metric;
529 struct rip_offset_list *offset;
530
531 if (event != NB_EV_APPLY)
532 return NB_OK;
533
534 direct = yang_dnode_get_enum(dnode, "../direction");
535 metric = yang_dnode_get_uint8(dnode, NULL);
536
537 offset = yang_dnode_get_entry(dnode, true);
538 offset->direct[direct].metric = metric;
539
540 return NB_OK;
541 }
542
543 /*
544 * XPath: /frr-ripd:ripd/instance/passive-default
545 */
546 static int ripd_instance_passive_default_modify(enum nb_event event,
547 const struct lyd_node *dnode,
548 union nb_resource *resource)
549 {
550 struct rip *rip;
551
552 if (event != NB_EV_APPLY)
553 return NB_OK;
554
555 rip = yang_dnode_get_entry(dnode, true);
556 rip->passive_default = yang_dnode_get_bool(dnode, NULL);
557 rip_passive_nondefault_clean(rip);
558
559 return NB_OK;
560 }
561
562 /*
563 * XPath: /frr-ripd:ripd/instance/passive-interface
564 */
565 static int ripd_instance_passive_interface_create(enum nb_event event,
566 const struct lyd_node *dnode,
567 union nb_resource *resource)
568 {
569 struct rip *rip;
570 const char *ifname;
571
572 if (event != NB_EV_APPLY)
573 return NB_OK;
574
575 rip = yang_dnode_get_entry(dnode, true);
576 ifname = yang_dnode_get_string(dnode, NULL);
577
578 return rip_passive_nondefault_set(rip, ifname);
579 }
580
581 static int ripd_instance_passive_interface_delete(enum nb_event event,
582 const struct lyd_node *dnode)
583 {
584 struct rip *rip;
585 const char *ifname;
586
587 if (event != NB_EV_APPLY)
588 return NB_OK;
589
590 rip = yang_dnode_get_entry(dnode, true);
591 ifname = yang_dnode_get_string(dnode, NULL);
592
593 return rip_passive_nondefault_unset(rip, ifname);
594 }
595
596 /*
597 * XPath: /frr-ripd:ripd/instance/non-passive-interface
598 */
599 static int
600 ripd_instance_non_passive_interface_create(enum nb_event event,
601 const struct lyd_node *dnode,
602 union nb_resource *resource)
603 {
604 struct rip *rip;
605 const char *ifname;
606
607 if (event != NB_EV_APPLY)
608 return NB_OK;
609
610 rip = yang_dnode_get_entry(dnode, true);
611 ifname = yang_dnode_get_string(dnode, NULL);
612
613 return rip_passive_nondefault_unset(rip, ifname);
614 }
615
616 static int
617 ripd_instance_non_passive_interface_delete(enum nb_event event,
618 const struct lyd_node *dnode)
619 {
620 struct rip *rip;
621 const char *ifname;
622
623 if (event != NB_EV_APPLY)
624 return NB_OK;
625
626 rip = yang_dnode_get_entry(dnode, true);
627 ifname = yang_dnode_get_string(dnode, NULL);
628
629 return rip_passive_nondefault_set(rip, ifname);
630 }
631
632 /*
633 * XPath: /frr-ripd:ripd/instance/redistribute
634 */
635 static int ripd_instance_redistribute_create(enum nb_event event,
636 const struct lyd_node *dnode,
637 union nb_resource *resource)
638 {
639 return NB_OK;
640 }
641
642 static int ripd_instance_redistribute_delete(enum nb_event event,
643 const struct lyd_node *dnode)
644 {
645 struct rip *rip;
646 int type;
647
648 if (event != NB_EV_APPLY)
649 return NB_OK;
650
651 rip = yang_dnode_get_entry(dnode, true);
652 type = yang_dnode_get_enum(dnode, "./protocol");
653
654 rip_redistribute_conf_delete(rip, type);
655
656 return NB_OK;
657 }
658
659 static void
660 ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
661 {
662 struct rip *rip;
663 int type;
664
665 rip = yang_dnode_get_entry(dnode, true);
666 type = yang_dnode_get_enum(dnode, "./protocol");
667
668 rip_redistribute_conf_update(rip, type);
669 }
670
671 /*
672 * XPath: /frr-ripd:ripd/instance/redistribute/route-map
673 */
674 static int
675 ripd_instance_redistribute_route_map_modify(enum nb_event event,
676 const struct lyd_node *dnode,
677 union nb_resource *resource)
678 {
679 struct rip *rip;
680 int type;
681 const char *rmap_name;
682
683 if (event != NB_EV_APPLY)
684 return NB_OK;
685
686 rip = yang_dnode_get_entry(dnode, true);
687 type = yang_dnode_get_enum(dnode, "../protocol");
688 rmap_name = yang_dnode_get_string(dnode, NULL);
689
690 if (rip->route_map[type].name)
691 free(rip->route_map[type].name);
692 rip->route_map[type].name = strdup(rmap_name);
693 rip->route_map[type].map = route_map_lookup_by_name(rmap_name);
694
695 return NB_OK;
696 }
697
698 static int
699 ripd_instance_redistribute_route_map_delete(enum nb_event event,
700 const struct lyd_node *dnode)
701 {
702 struct rip *rip;
703 int type;
704
705 if (event != NB_EV_APPLY)
706 return NB_OK;
707
708 rip = yang_dnode_get_entry(dnode, true);
709 type = yang_dnode_get_enum(dnode, "../protocol");
710
711 free(rip->route_map[type].name);
712 rip->route_map[type].name = NULL;
713 rip->route_map[type].map = NULL;
714
715 return NB_OK;
716 }
717
718 /*
719 * XPath: /frr-ripd:ripd/instance/redistribute/metric
720 */
721 static int
722 ripd_instance_redistribute_metric_modify(enum nb_event event,
723 const struct lyd_node *dnode,
724 union nb_resource *resource)
725 {
726 struct rip *rip;
727 int type;
728 uint8_t metric;
729
730 if (event != NB_EV_APPLY)
731 return NB_OK;
732
733 rip = yang_dnode_get_entry(dnode, true);
734 type = yang_dnode_get_enum(dnode, "../protocol");
735 metric = yang_dnode_get_uint8(dnode, NULL);
736
737 rip->route_map[type].metric_config = true;
738 rip->route_map[type].metric = metric;
739
740 return NB_OK;
741 }
742
743 static int
744 ripd_instance_redistribute_metric_delete(enum nb_event event,
745 const struct lyd_node *dnode)
746 {
747 struct rip *rip;
748 int type;
749
750 if (event != NB_EV_APPLY)
751 return NB_OK;
752
753 rip = yang_dnode_get_entry(dnode, true);
754 type = yang_dnode_get_enum(dnode, "../protocol");
755
756 rip->route_map[type].metric_config = false;
757 rip->route_map[type].metric = 0;
758
759 return NB_OK;
760 }
761
762 /*
763 * XPath: /frr-ripd:ripd/instance/static-route
764 */
765 static int ripd_instance_static_route_create(enum nb_event event,
766 const struct lyd_node *dnode,
767 union nb_resource *resource)
768 {
769 struct rip *rip;
770 struct nexthop nh;
771 struct prefix_ipv4 p;
772
773 if (event != NB_EV_APPLY)
774 return NB_OK;
775
776 rip = yang_dnode_get_entry(dnode, true);
777 yang_dnode_get_ipv4p(&p, dnode, NULL);
778 apply_mask_ipv4(&p);
779
780 memset(&nh, 0, sizeof(nh));
781 nh.type = NEXTHOP_TYPE_IPV4;
782 rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0,
783 0, 0);
784
785 return NB_OK;
786 }
787
788 static int ripd_instance_static_route_delete(enum nb_event event,
789 const struct lyd_node *dnode)
790 {
791 struct rip *rip;
792 struct prefix_ipv4 p;
793
794 if (event != NB_EV_APPLY)
795 return NB_OK;
796
797 rip = yang_dnode_get_entry(dnode, true);
798 yang_dnode_get_ipv4p(&p, dnode, NULL);
799 apply_mask_ipv4(&p);
800
801 rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
802
803 return NB_OK;
804 }
805
806 /*
807 * XPath: /frr-ripd:ripd/instance/timers/
808 */
809 static void ripd_instance_timers_apply_finish(const struct lyd_node *dnode)
810 {
811 struct rip *rip;
812
813 rip = yang_dnode_get_entry(dnode, true);
814
815 /* Reset update timer thread. */
816 rip_event(rip, RIP_UPDATE_EVENT, 0);
817 }
818
819 /*
820 * XPath: /frr-ripd:ripd/instance/timers/flush-interval
821 */
822 static int
823 ripd_instance_timers_flush_interval_modify(enum nb_event event,
824 const struct lyd_node *dnode,
825 union nb_resource *resource)
826 {
827 struct rip *rip;
828
829 if (event != NB_EV_APPLY)
830 return NB_OK;
831
832 rip = yang_dnode_get_entry(dnode, true);
833 rip->garbage_time = yang_dnode_get_uint32(dnode, NULL);
834
835 return NB_OK;
836 }
837
838 /*
839 * XPath: /frr-ripd:ripd/instance/timers/holddown-interval
840 */
841 static int
842 ripd_instance_timers_holddown_interval_modify(enum nb_event event,
843 const struct lyd_node *dnode,
844 union nb_resource *resource)
845 {
846 struct rip *rip;
847
848 if (event != NB_EV_APPLY)
849 return NB_OK;
850
851 rip = yang_dnode_get_entry(dnode, true);
852 rip->timeout_time = yang_dnode_get_uint32(dnode, NULL);
853
854 return NB_OK;
855 }
856
857 /*
858 * XPath: /frr-ripd:ripd/instance/timers/update-interval
859 */
860 static int
861 ripd_instance_timers_update_interval_modify(enum nb_event event,
862 const struct lyd_node *dnode,
863 union nb_resource *resource)
864 {
865 struct rip *rip;
866
867 if (event != NB_EV_APPLY)
868 return NB_OK;
869
870 rip = yang_dnode_get_entry(dnode, true);
871 rip->update_time = yang_dnode_get_uint32(dnode, NULL);
872
873 return NB_OK;
874 }
875
876 /*
877 * XPath: /frr-ripd:ripd/instance/version/receive
878 */
879 static int ripd_instance_version_receive_modify(enum nb_event event,
880 const struct lyd_node *dnode,
881 union nb_resource *resource)
882 {
883 struct rip *rip;
884
885 if (event != NB_EV_APPLY)
886 return NB_OK;
887
888 rip = yang_dnode_get_entry(dnode, true);
889 rip->version_recv = yang_dnode_get_enum(dnode, NULL);
890
891 return NB_OK;
892 }
893
894 /*
895 * XPath: /frr-ripd:ripd/instance/version/send
896 */
897 static int ripd_instance_version_send_modify(enum nb_event event,
898 const struct lyd_node *dnode,
899 union nb_resource *resource)
900 {
901 struct rip *rip;
902
903 if (event != NB_EV_APPLY)
904 return NB_OK;
905
906 rip = yang_dnode_get_entry(dnode, true);
907 rip->version_send = yang_dnode_get_enum(dnode, NULL);
908
909 return NB_OK;
910 }
911
912 /*
913 * XPath: /frr-interface:lib/interface/frr-ripd:rip/split-horizon
914 */
915 static int lib_interface_rip_split_horizon_modify(enum nb_event event,
916 const struct lyd_node *dnode,
917 union nb_resource *resource)
918 {
919 struct interface *ifp;
920 struct rip_interface *ri;
921
922 if (event != NB_EV_APPLY)
923 return NB_OK;
924
925 ifp = yang_dnode_get_entry(dnode, true);
926 ri = ifp->info;
927 ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
928
929 return NB_OK;
930 }
931
932 /*
933 * XPath: /frr-interface:lib/interface/frr-ripd:rip/v2-broadcast
934 */
935 static int lib_interface_rip_v2_broadcast_modify(enum nb_event event,
936 const struct lyd_node *dnode,
937 union nb_resource *resource)
938 {
939 struct interface *ifp;
940 struct rip_interface *ri;
941
942 if (event != NB_EV_APPLY)
943 return NB_OK;
944
945 ifp = yang_dnode_get_entry(dnode, true);
946 ri = ifp->info;
947 ri->v2_broadcast = yang_dnode_get_bool(dnode, NULL);
948
949 return NB_OK;
950 }
951
952 /*
953 * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-receive
954 */
955 static int
956 lib_interface_rip_version_receive_modify(enum nb_event event,
957 const struct lyd_node *dnode,
958 union nb_resource *resource)
959 {
960 struct interface *ifp;
961 struct rip_interface *ri;
962
963 if (event != NB_EV_APPLY)
964 return NB_OK;
965
966 ifp = yang_dnode_get_entry(dnode, true);
967 ri = ifp->info;
968 ri->ri_receive = yang_dnode_get_enum(dnode, NULL);
969
970 return NB_OK;
971 }
972
973 /*
974 * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-send
975 */
976 static int lib_interface_rip_version_send_modify(enum nb_event event,
977 const struct lyd_node *dnode,
978 union nb_resource *resource)
979 {
980 struct interface *ifp;
981 struct rip_interface *ri;
982
983 if (event != NB_EV_APPLY)
984 return NB_OK;
985
986 ifp = yang_dnode_get_entry(dnode, true);
987 ri = ifp->info;
988 ri->ri_send = yang_dnode_get_enum(dnode, NULL);
989
990 return NB_OK;
991 }
992
993 /*
994 * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode
995 */
996 static int lib_interface_rip_authentication_scheme_mode_modify(
997 enum nb_event event, const struct lyd_node *dnode,
998 union nb_resource *resource)
999 {
1000 struct interface *ifp;
1001 struct rip_interface *ri;
1002
1003 if (event != NB_EV_APPLY)
1004 return NB_OK;
1005
1006 ifp = yang_dnode_get_entry(dnode, true);
1007 ri = ifp->info;
1008 ri->auth_type = yang_dnode_get_enum(dnode, NULL);
1009
1010 return NB_OK;
1011 }
1012
1013 /*
1014 * XPath:
1015 * /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length
1016 */
1017 static int lib_interface_rip_authentication_scheme_md5_auth_length_modify(
1018 enum nb_event event, const struct lyd_node *dnode,
1019 union nb_resource *resource)
1020 {
1021 struct interface *ifp;
1022 struct rip_interface *ri;
1023
1024 if (event != NB_EV_APPLY)
1025 return NB_OK;
1026
1027 ifp = yang_dnode_get_entry(dnode, true);
1028 ri = ifp->info;
1029 ri->md5_auth_len = yang_dnode_get_enum(dnode, NULL);
1030
1031 return NB_OK;
1032 }
1033
1034 static int lib_interface_rip_authentication_scheme_md5_auth_length_delete(
1035 enum nb_event event, const struct lyd_node *dnode)
1036 {
1037 struct interface *ifp;
1038 struct rip_interface *ri;
1039
1040 if (event != NB_EV_APPLY)
1041 return NB_OK;
1042
1043 ifp = yang_dnode_get_entry(dnode, true);
1044 ri = ifp->info;
1045 ri->md5_auth_len = yang_get_default_enum(
1046 "%s/authentication-scheme/md5-auth-length", RIP_IFACE);
1047
1048 return NB_OK;
1049 }
1050
1051 /*
1052 * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-password
1053 */
1054 static int
1055 lib_interface_rip_authentication_password_modify(enum nb_event event,
1056 const struct lyd_node *dnode,
1057 union nb_resource *resource)
1058 {
1059 struct interface *ifp;
1060 struct rip_interface *ri;
1061
1062 if (event != NB_EV_APPLY)
1063 return NB_OK;
1064
1065 ifp = yang_dnode_get_entry(dnode, true);
1066 ri = ifp->info;
1067 if (ri->auth_str)
1068 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
1069 ri->auth_str = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
1070 yang_dnode_get_string(dnode, NULL));
1071
1072 return NB_OK;
1073 }
1074
1075 static int
1076 lib_interface_rip_authentication_password_delete(enum nb_event event,
1077 const struct lyd_node *dnode)
1078 {
1079 struct interface *ifp;
1080 struct rip_interface *ri;
1081
1082 if (event != NB_EV_APPLY)
1083 return NB_OK;
1084
1085 ifp = yang_dnode_get_entry(dnode, true);
1086 ri = ifp->info;
1087 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
1088
1089 return NB_OK;
1090 }
1091
1092 /*
1093 * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain
1094 */
1095 static int
1096 lib_interface_rip_authentication_key_chain_modify(enum nb_event event,
1097 const struct lyd_node *dnode,
1098 union nb_resource *resource)
1099 {
1100 struct interface *ifp;
1101 struct rip_interface *ri;
1102
1103 if (event != NB_EV_APPLY)
1104 return NB_OK;
1105
1106 ifp = yang_dnode_get_entry(dnode, true);
1107 ri = ifp->info;
1108 if (ri->key_chain)
1109 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
1110 ri->key_chain = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
1111 yang_dnode_get_string(dnode, NULL));
1112
1113 return NB_OK;
1114 }
1115
1116 static int
1117 lib_interface_rip_authentication_key_chain_delete(enum nb_event event,
1118 const struct lyd_node *dnode)
1119 {
1120 struct interface *ifp;
1121 struct rip_interface *ri;
1122
1123 if (event != NB_EV_APPLY)
1124 return NB_OK;
1125
1126 ifp = yang_dnode_get_entry(dnode, true);
1127 ri = ifp->info;
1128 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
1129
1130 return NB_OK;
1131 }
1132
1133 /*
1134 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor
1135 */
1136 static const void *
1137 ripd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
1138 const void *list_entry)
1139 {
1140 const struct rip *rip = parent_list_entry;
1141 struct listnode *node;
1142
1143 if (list_entry == NULL)
1144 node = listhead(rip->peer_list);
1145 else
1146 node = listnextnode((struct listnode *)list_entry);
1147
1148 return node;
1149 }
1150
1151 static int
1152 ripd_instance_state_neighbors_neighbor_get_keys(const void *list_entry,
1153 struct yang_list_keys *keys)
1154 {
1155 const struct listnode *node = list_entry;
1156 const struct rip_peer *peer = listgetdata(node);
1157
1158 keys->num = 1;
1159 (void)inet_ntop(AF_INET, &peer->addr, keys->key[0],
1160 sizeof(keys->key[0]));
1161
1162 return NB_OK;
1163 }
1164
1165 static const void *ripd_instance_state_neighbors_neighbor_lookup_entry(
1166 const void *parent_list_entry, const struct yang_list_keys *keys)
1167 {
1168 const struct rip *rip = parent_list_entry;
1169 struct in_addr address;
1170 struct rip_peer *peer;
1171 struct listnode *node;
1172
1173 yang_str2ipv4(keys->key[0], &address);
1174
1175 for (ALL_LIST_ELEMENTS_RO(rip->peer_list, node, peer)) {
1176 if (IPV4_ADDR_SAME(&peer->addr, &address))
1177 return node;
1178 }
1179
1180 return NULL;
1181 }
1182
1183 /*
1184 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/address
1185 */
1186 static struct yang_data *
1187 ripd_instance_state_neighbors_neighbor_address_get_elem(const char *xpath,
1188 const void *list_entry)
1189 {
1190 const struct listnode *node = list_entry;
1191 const struct rip_peer *peer = listgetdata(node);
1192
1193 return yang_data_new_ipv4(xpath, &peer->addr);
1194 }
1195
1196 /*
1197 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/last-update
1198 */
1199 static struct yang_data *
1200 ripd_instance_state_neighbors_neighbor_last_update_get_elem(
1201 const char *xpath, const void *list_entry)
1202 {
1203 /* TODO: yang:date-and-time is tricky */
1204 return NULL;
1205 }
1206
1207 /*
1208 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd
1209 */
1210 static struct yang_data *
1211 ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
1212 const char *xpath, const void *list_entry)
1213 {
1214 const struct listnode *node = list_entry;
1215 const struct rip_peer *peer = listgetdata(node);
1216
1217 return yang_data_new_uint32(xpath, peer->recv_badpackets);
1218 }
1219
1220 /*
1221 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd
1222 */
1223 static struct yang_data *
1224 ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
1225 const char *xpath, const void *list_entry)
1226 {
1227 const struct listnode *node = list_entry;
1228 const struct rip_peer *peer = listgetdata(node);
1229
1230 return yang_data_new_uint32(xpath, peer->recv_badroutes);
1231 }
1232
1233 /*
1234 * XPath: /frr-ripd:ripd/instance/state/routes/route
1235 */
1236 static const void *
1237 ripd_instance_state_routes_route_get_next(const void *parent_list_entry,
1238 const void *list_entry)
1239 {
1240 const struct rip *rip = parent_list_entry;
1241 struct route_node *rn;
1242
1243 if (list_entry == NULL)
1244 rn = route_top(rip->table);
1245 else
1246 rn = route_next((struct route_node *)list_entry);
1247 while (rn && rn->info == NULL)
1248 rn = route_next(rn);
1249
1250 return rn;
1251 }
1252
1253 static int
1254 ripd_instance_state_routes_route_get_keys(const void *list_entry,
1255 struct yang_list_keys *keys)
1256 {
1257 const struct route_node *rn = list_entry;
1258
1259 keys->num = 1;
1260 (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0]));
1261
1262 return NB_OK;
1263 }
1264
1265 static const void *
1266 ripd_instance_state_routes_route_lookup_entry(const void *parent_list_entry,
1267 const struct yang_list_keys *keys)
1268 {
1269 const struct rip *rip = parent_list_entry;
1270 struct prefix prefix;
1271 struct route_node *rn;
1272
1273 yang_str2ipv4p(keys->key[0], &prefix);
1274
1275 rn = route_node_lookup(rip->table, &prefix);
1276 if (!rn || !rn->info)
1277 return NULL;
1278
1279 route_unlock_node(rn);
1280
1281 return rn;
1282 }
1283
1284 /*
1285 * XPath: /frr-ripd:ripd/instance/state/routes/route/prefix
1286 */
1287 static struct yang_data *
1288 ripd_instance_state_routes_route_prefix_get_elem(const char *xpath,
1289 const void *list_entry)
1290 {
1291 const struct route_node *rn = list_entry;
1292 const struct rip_info *rinfo = listnode_head(rn->info);
1293
1294 return yang_data_new_ipv4p(xpath, &rinfo->rp->p);
1295 }
1296
1297 /*
1298 * XPath: /frr-ripd:ripd/instance/state/routes/route/next-hop
1299 */
1300 static struct yang_data *
1301 ripd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
1302 const void *list_entry)
1303 {
1304 const struct route_node *rn = list_entry;
1305 const struct rip_info *rinfo = listnode_head(rn->info);
1306
1307 switch (rinfo->nh.type) {
1308 case NEXTHOP_TYPE_IPV4:
1309 case NEXTHOP_TYPE_IPV4_IFINDEX:
1310 return yang_data_new_ipv4(xpath, &rinfo->nh.gate.ipv4);
1311 default:
1312 return NULL;
1313 }
1314 }
1315
1316 /*
1317 * XPath: /frr-ripd:ripd/instance/state/routes/route/interface
1318 */
1319 static struct yang_data *
1320 ripd_instance_state_routes_route_interface_get_elem(const char *xpath,
1321 const void *list_entry)
1322 {
1323 const struct route_node *rn = list_entry;
1324 const struct rip_info *rinfo = listnode_head(rn->info);
1325 const struct rip *rip = rip_info_get_instance(rinfo);
1326
1327 switch (rinfo->nh.type) {
1328 case NEXTHOP_TYPE_IFINDEX:
1329 case NEXTHOP_TYPE_IPV4_IFINDEX:
1330 return yang_data_new_string(
1331 xpath,
1332 ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id));
1333 default:
1334 return NULL;
1335 }
1336 }
1337
1338 /*
1339 * XPath: /frr-ripd:ripd/instance/state/routes/route/metric
1340 */
1341 static struct yang_data *
1342 ripd_instance_state_routes_route_metric_get_elem(const char *xpath,
1343 const void *list_entry)
1344 {
1345 const struct route_node *rn = list_entry;
1346 const struct rip_info *rinfo = listnode_head(rn->info);
1347
1348 return yang_data_new_uint8(xpath, rinfo->metric);
1349 }
1350
1351 /*
1352 * XPath: /frr-ripd:clear-rip-route
1353 */
1354 static int clear_rip_route_rpc(const char *xpath, const struct list *input,
1355 struct list *output)
1356 {
1357 struct rip *rip;
1358 struct route_node *rp;
1359 struct rip_info *rinfo;
1360 struct list *list;
1361 struct listnode *listnode;
1362
1363 rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
1364 if (!rip)
1365 return NB_OK;
1366
1367 /* Clear received RIP routes */
1368 for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
1369 list = rp->info;
1370 if (!list)
1371 continue;
1372
1373 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
1374 if (!rip_route_rte(rinfo))
1375 continue;
1376
1377 if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
1378 rip_zebra_ipv4_delete(rip, rp);
1379 break;
1380 }
1381
1382 if (rinfo) {
1383 RIP_TIMER_OFF(rinfo->t_timeout);
1384 RIP_TIMER_OFF(rinfo->t_garbage_collect);
1385 listnode_delete(list, rinfo);
1386 rip_info_free(rinfo);
1387 }
1388
1389 if (list_isempty(list)) {
1390 list_delete(&list);
1391 rp->info = NULL;
1392 route_unlock_node(rp);
1393 }
1394 }
1395
1396 return NB_OK;
1397 }
1398
1399 /*
1400 * XPath: /frr-ripd:authentication-type-failure
1401 */
1402 void ripd_notif_send_auth_type_failure(const char *ifname)
1403 {
1404 const char *xpath = "/frr-ripd:authentication-type-failure";
1405 struct list *arguments;
1406 char xpath_arg[XPATH_MAXLEN];
1407 struct yang_data *data;
1408
1409 arguments = yang_data_list_new();
1410
1411 snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath);
1412 data = yang_data_new_string(xpath_arg, ifname);
1413 listnode_add(arguments, data);
1414
1415 nb_notification_send(xpath, arguments);
1416 }
1417
1418 /*
1419 * XPath: /frr-ripd:authentication-failure
1420 */
1421 void ripd_notif_send_auth_failure(const char *ifname)
1422 {
1423 const char *xpath = "/frr-ripd:authentication-failure";
1424 struct list *arguments;
1425 char xpath_arg[XPATH_MAXLEN];
1426 struct yang_data *data;
1427
1428 arguments = yang_data_list_new();
1429
1430 snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath);
1431 data = yang_data_new_string(xpath_arg, ifname);
1432 listnode_add(arguments, data);
1433
1434 nb_notification_send(xpath, arguments);
1435 }
1436
1437 /* clang-format off */
1438 const struct frr_yang_module_info frr_ripd_info = {
1439 .name = "frr-ripd",
1440 .nodes = {
1441 {
1442 .xpath = "/frr-ripd:ripd/instance",
1443 .cbs.create = ripd_instance_create,
1444 .cbs.delete = ripd_instance_delete,
1445 .cbs.get_next = ripd_instance_get_next,
1446 .cbs.get_keys = ripd_instance_get_keys,
1447 .cbs.lookup_entry = ripd_instance_lookup_entry,
1448 .cbs.cli_show = cli_show_router_rip,
1449 },
1450 {
1451 .xpath = "/frr-ripd:ripd/instance/allow-ecmp",
1452 .cbs.modify = ripd_instance_allow_ecmp_modify,
1453 .cbs.cli_show = cli_show_rip_allow_ecmp,
1454 },
1455 {
1456 .xpath = "/frr-ripd:ripd/instance/default-information-originate",
1457 .cbs.modify = ripd_instance_default_information_originate_modify,
1458 .cbs.cli_show = cli_show_rip_default_information_originate,
1459 },
1460 {
1461 .xpath = "/frr-ripd:ripd/instance/default-metric",
1462 .cbs.modify = ripd_instance_default_metric_modify,
1463 .cbs.cli_show = cli_show_rip_default_metric,
1464 },
1465 {
1466 .xpath = "/frr-ripd:ripd/instance/distance/default",
1467 .cbs.modify = ripd_instance_distance_default_modify,
1468 .cbs.cli_show = cli_show_rip_distance,
1469 },
1470 {
1471 .xpath = "/frr-ripd:ripd/instance/distance/source",
1472 .cbs.create = ripd_instance_distance_source_create,
1473 .cbs.delete = ripd_instance_distance_source_delete,
1474 .cbs.cli_show = cli_show_rip_distance_source,
1475 },
1476 {
1477 .xpath = "/frr-ripd:ripd/instance/distance/source/distance",
1478 .cbs.modify = ripd_instance_distance_source_distance_modify,
1479 },
1480 {
1481 .xpath = "/frr-ripd:ripd/instance/distance/source/access-list",
1482 .cbs.modify = ripd_instance_distance_source_access_list_modify,
1483 .cbs.delete = ripd_instance_distance_source_access_list_delete,
1484 },
1485 {
1486 .xpath = "/frr-ripd:ripd/instance/explicit-neighbor",
1487 .cbs.create = ripd_instance_explicit_neighbor_create,
1488 .cbs.delete = ripd_instance_explicit_neighbor_delete,
1489 .cbs.cli_show = cli_show_rip_neighbor,
1490 },
1491 {
1492 .xpath = "/frr-ripd:ripd/instance/network",
1493 .cbs.create = ripd_instance_network_create,
1494 .cbs.delete = ripd_instance_network_delete,
1495 .cbs.cli_show = cli_show_rip_network_prefix,
1496 },
1497 {
1498 .xpath = "/frr-ripd:ripd/instance/interface",
1499 .cbs.create = ripd_instance_interface_create,
1500 .cbs.delete = ripd_instance_interface_delete,
1501 .cbs.cli_show = cli_show_rip_network_interface,
1502 },
1503 {
1504 .xpath = "/frr-ripd:ripd/instance/offset-list",
1505 .cbs.create = ripd_instance_offset_list_create,
1506 .cbs.delete = ripd_instance_offset_list_delete,
1507 .cbs.cli_show = cli_show_rip_offset_list,
1508 },
1509 {
1510 .xpath = "/frr-ripd:ripd/instance/offset-list/access-list",
1511 .cbs.modify = ripd_instance_offset_list_access_list_modify,
1512 },
1513 {
1514 .xpath = "/frr-ripd:ripd/instance/offset-list/metric",
1515 .cbs.modify = ripd_instance_offset_list_metric_modify,
1516 },
1517 {
1518 .xpath = "/frr-ripd:ripd/instance/passive-default",
1519 .cbs.modify = ripd_instance_passive_default_modify,
1520 .cbs.cli_show = cli_show_rip_passive_default,
1521 },
1522 {
1523 .xpath = "/frr-ripd:ripd/instance/passive-interface",
1524 .cbs.create = ripd_instance_passive_interface_create,
1525 .cbs.delete = ripd_instance_passive_interface_delete,
1526 .cbs.cli_show = cli_show_rip_passive_interface,
1527 },
1528 {
1529 .xpath = "/frr-ripd:ripd/instance/non-passive-interface",
1530 .cbs.create = ripd_instance_non_passive_interface_create,
1531 .cbs.delete = ripd_instance_non_passive_interface_delete,
1532 .cbs.cli_show = cli_show_rip_non_passive_interface,
1533 },
1534 {
1535 .xpath = "/frr-ripd:ripd/instance/redistribute",
1536 .cbs.create = ripd_instance_redistribute_create,
1537 .cbs.delete = ripd_instance_redistribute_delete,
1538 .cbs.apply_finish = ripd_instance_redistribute_apply_finish,
1539 .cbs.cli_show = cli_show_rip_redistribute,
1540 },
1541 {
1542 .xpath = "/frr-ripd:ripd/instance/redistribute/route-map",
1543 .cbs.modify = ripd_instance_redistribute_route_map_modify,
1544 .cbs.delete = ripd_instance_redistribute_route_map_delete,
1545 },
1546 {
1547 .xpath = "/frr-ripd:ripd/instance/redistribute/metric",
1548 .cbs.modify = ripd_instance_redistribute_metric_modify,
1549 .cbs.delete = ripd_instance_redistribute_metric_delete,
1550 },
1551 {
1552 .xpath = "/frr-ripd:ripd/instance/static-route",
1553 .cbs.create = ripd_instance_static_route_create,
1554 .cbs.delete = ripd_instance_static_route_delete,
1555 .cbs.cli_show = cli_show_rip_route,
1556 },
1557 {
1558 .xpath = "/frr-ripd:ripd/instance/timers",
1559 .cbs.apply_finish = ripd_instance_timers_apply_finish,
1560 .cbs.cli_show = cli_show_rip_timers,
1561 },
1562 {
1563 .xpath = "/frr-ripd:ripd/instance/timers/flush-interval",
1564 .cbs.modify = ripd_instance_timers_flush_interval_modify,
1565 },
1566 {
1567 .xpath = "/frr-ripd:ripd/instance/timers/holddown-interval",
1568 .cbs.modify = ripd_instance_timers_holddown_interval_modify,
1569 },
1570 {
1571 .xpath = "/frr-ripd:ripd/instance/timers/update-interval",
1572 .cbs.modify = ripd_instance_timers_update_interval_modify,
1573 },
1574 {
1575 .xpath = "/frr-ripd:ripd/instance/version",
1576 .cbs.cli_show = cli_show_rip_version,
1577 },
1578 {
1579 .xpath = "/frr-ripd:ripd/instance/version/receive",
1580 .cbs.modify = ripd_instance_version_receive_modify,
1581 },
1582 {
1583 .xpath = "/frr-ripd:ripd/instance/version/send",
1584 .cbs.modify = ripd_instance_version_send_modify,
1585 },
1586 {
1587 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/split-horizon",
1588 .cbs.modify = lib_interface_rip_split_horizon_modify,
1589 .cbs.cli_show = cli_show_ip_rip_split_horizon,
1590 },
1591 {
1592 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/v2-broadcast",
1593 .cbs.modify = lib_interface_rip_v2_broadcast_modify,
1594 .cbs.cli_show = cli_show_ip_rip_v2_broadcast,
1595 },
1596 {
1597 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-receive",
1598 .cbs.modify = lib_interface_rip_version_receive_modify,
1599 .cbs.cli_show = cli_show_ip_rip_receive_version,
1600 },
1601 {
1602 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-send",
1603 .cbs.modify = lib_interface_rip_version_send_modify,
1604 .cbs.cli_show = cli_show_ip_rip_send_version,
1605 },
1606 {
1607 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme",
1608 .cbs.cli_show = cli_show_ip_rip_authentication_scheme,
1609 },
1610 {
1611 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode",
1612 .cbs.modify = lib_interface_rip_authentication_scheme_mode_modify,
1613 },
1614 {
1615 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length",
1616 .cbs.modify = lib_interface_rip_authentication_scheme_md5_auth_length_modify,
1617 .cbs.delete = lib_interface_rip_authentication_scheme_md5_auth_length_delete,
1618 },
1619 {
1620 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password",
1621 .cbs.modify = lib_interface_rip_authentication_password_modify,
1622 .cbs.delete = lib_interface_rip_authentication_password_delete,
1623 .cbs.cli_show = cli_show_ip_rip_authentication_string,
1624 },
1625 {
1626 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain",
1627 .cbs.modify = lib_interface_rip_authentication_key_chain_modify,
1628 .cbs.delete = lib_interface_rip_authentication_key_chain_delete,
1629 .cbs.cli_show = cli_show_ip_rip_authentication_key_chain,
1630 },
1631 {
1632 .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor",
1633 .cbs.get_next = ripd_instance_state_neighbors_neighbor_get_next,
1634 .cbs.get_keys = ripd_instance_state_neighbors_neighbor_get_keys,
1635 .cbs.lookup_entry = ripd_instance_state_neighbors_neighbor_lookup_entry,
1636 },
1637 {
1638 .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/address",
1639 .cbs.get_elem = ripd_instance_state_neighbors_neighbor_address_get_elem,
1640 },
1641 {
1642 .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/last-update",
1643 .cbs.get_elem = ripd_instance_state_neighbors_neighbor_last_update_get_elem,
1644 },
1645 {
1646 .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd",
1647 .cbs.get_elem = ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
1648 },
1649 {
1650 .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd",
1651 .cbs.get_elem = ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
1652 },
1653 {
1654 .xpath = "/frr-ripd:ripd/instance/state/routes/route",
1655 .cbs.get_next = ripd_instance_state_routes_route_get_next,
1656 .cbs.get_keys = ripd_instance_state_routes_route_get_keys,
1657 .cbs.lookup_entry = ripd_instance_state_routes_route_lookup_entry,
1658 },
1659 {
1660 .xpath = "/frr-ripd:ripd/instance/state/routes/route/prefix",
1661 .cbs.get_elem = ripd_instance_state_routes_route_prefix_get_elem,
1662 },
1663 {
1664 .xpath = "/frr-ripd:ripd/instance/state/routes/route/next-hop",
1665 .cbs.get_elem = ripd_instance_state_routes_route_next_hop_get_elem,
1666 },
1667 {
1668 .xpath = "/frr-ripd:ripd/instance/state/routes/route/interface",
1669 .cbs.get_elem = ripd_instance_state_routes_route_interface_get_elem,
1670 },
1671 {
1672 .xpath = "/frr-ripd:ripd/instance/state/routes/route/metric",
1673 .cbs.get_elem = ripd_instance_state_routes_route_metric_get_elem,
1674 },
1675 {
1676 .xpath = "/frr-ripd:clear-rip-route",
1677 .cbs.rpc = clear_rip_route_rpc,
1678 },
1679 {
1680 .xpath = NULL,
1681 },
1682 }
1683 };