]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_northbound.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / ripngd / ripng_northbound.c
CommitLineData
e9ce224b
RW
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"
49e06d25 30#include "agg_table.h"
e9ce224b
RW
31#include "northbound.h"
32#include "libfrr.h"
33
34#include "ripngd/ripngd.h"
6fc29385 35#include "ripngd/ripng_route.h"
e9ce224b
RW
36#include "ripngd/ripng_cli.h"
37
38/*
39 * XPath: /frr-ripngd:ripngd/instance
40 */
41static int ripngd_instance_create(enum nb_event event,
42 const struct lyd_node *dnode,
43 union nb_resource *resource)
44{
9a12e9e5
RW
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
e9ce224b
RW
66 return NB_OK;
67}
68
69static int ripngd_instance_delete(enum nb_event event,
70 const struct lyd_node *dnode)
71{
9a12e9e5
RW
72 if (event != NB_EV_APPLY)
73 return NB_OK;
74
75 ripng_clean();
76
e9ce224b
RW
77 return NB_OK;
78}
79
80/*
81 * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
82 */
83static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
84 const struct lyd_node *dnode,
85 union nb_resource *resource)
86{
1e42a07c
RW
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
e9ce224b
RW
94 return NB_OK;
95}
96
97/*
98 * XPath: /frr-ripngd:ripngd/instance/default-information-originate
99 */
100static int ripngd_instance_default_information_originate_modify(
101 enum nb_event event, const struct lyd_node *dnode,
102 union nb_resource *resource)
103{
54b56562
RW
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
e9ce224b
RW
120 return NB_OK;
121}
122
123/*
124 * XPath: /frr-ripngd:ripngd/instance/default-metric
125 */
126static int ripngd_instance_default_metric_modify(enum nb_event event,
127 const struct lyd_node *dnode,
128 union nb_resource *resource)
129{
ad8778c0
RW
130 if (event != NB_EV_APPLY)
131 return NB_OK;
132
133 ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
134
e9ce224b
RW
135 return NB_OK;
136}
137
138/*
139 * XPath: /frr-ripngd:ripngd/instance/network
140 */
141static int ripngd_instance_network_create(enum nb_event event,
142 const struct lyd_node *dnode,
143 union nb_resource *resource)
144{
cc48702b
RW
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);
e9ce224b
RW
154}
155
156static int ripngd_instance_network_delete(enum nb_event event,
157 const struct lyd_node *dnode)
158{
cc48702b
RW
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);
e9ce224b
RW
168}
169
170/*
171 * XPath: /frr-ripngd:ripngd/instance/interface
172 */
173static int ripngd_instance_interface_create(enum nb_event event,
174 const struct lyd_node *dnode,
175 union nb_resource *resource)
176{
cc48702b
RW
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);
e9ce224b
RW
185}
186
187static int ripngd_instance_interface_delete(enum nb_event event,
188 const struct lyd_node *dnode)
189{
cc48702b
RW
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);
e9ce224b
RW
198}
199
200/*
201 * XPath: /frr-ripngd:ripngd/instance/offset-list
202 */
203static int ripngd_instance_offset_list_create(enum nb_event event,
204 const struct lyd_node *dnode,
205 union nb_resource *resource)
206{
b09956ca
RW
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
e9ce224b
RW
218 return NB_OK;
219}
220
221static int ripngd_instance_offset_list_delete(enum nb_event event,
222 const struct lyd_node *dnode)
223{
b09956ca
RW
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
e9ce224b
RW
241 return NB_OK;
242}
243
244/*
245 * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
246 */
247static int
248ripngd_instance_offset_list_access_list_modify(enum nb_event event,
249 const struct lyd_node *dnode,
250 union nb_resource *resource)
251{
b09956ca
RW
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
e9ce224b
RW
267 return NB_OK;
268}
269
270/*
271 * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
272 */
273static int
274ripngd_instance_offset_list_metric_modify(enum nb_event event,
275 const struct lyd_node *dnode,
276 union nb_resource *resource)
277{
b09956ca
RW
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
e9ce224b
RW
291 return NB_OK;
292}
293
294/*
295 * XPath: /frr-ripngd:ripngd/instance/passive-interface
296 */
297static int
298ripngd_instance_passive_interface_create(enum nb_event event,
299 const struct lyd_node *dnode,
300 union nb_resource *resource)
301{
22e8c7ae
RW
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);
e9ce224b
RW
310}
311
312static int
313ripngd_instance_passive_interface_delete(enum nb_event event,
314 const struct lyd_node *dnode)
315{
22e8c7ae
RW
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);
e9ce224b
RW
324}
325
326/*
327 * XPath: /frr-ripngd:ripngd/instance/redistribute
328 */
329static int ripngd_instance_redistribute_create(enum nb_event event,
330 const struct lyd_node *dnode,
331 union nb_resource *resource)
332{
e9ce224b
RW
333 return NB_OK;
334}
335
336static int ripngd_instance_redistribute_delete(enum nb_event event,
337 const struct lyd_node *dnode)
338{
db2038c7
RW
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
e9ce224b
RW
348 return NB_OK;
349}
350
db2038c7
RW
351static void
352ripngd_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
e9ce224b
RW
360/*
361 * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
362 */
363static int
364ripngd_instance_redistribute_route_map_modify(enum nb_event event,
365 const struct lyd_node *dnode,
366 union nb_resource *resource)
367{
db2038c7
RW
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
e9ce224b
RW
382 return NB_OK;
383}
384
385static int
386ripngd_instance_redistribute_route_map_delete(enum nb_event event,
387 const struct lyd_node *dnode)
388{
db2038c7
RW
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
e9ce224b
RW
400 return NB_OK;
401}
402
403/*
404 * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
405 */
406static int
407ripngd_instance_redistribute_metric_modify(enum nb_event event,
408 const struct lyd_node *dnode,
409 union nb_resource *resource)
410{
db2038c7
RW
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
e9ce224b
RW
423 return NB_OK;
424}
425
426static int
427ripngd_instance_redistribute_metric_delete(enum nb_event event,
428 const struct lyd_node *dnode)
429{
db2038c7
RW
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
e9ce224b
RW
440 return NB_OK;
441}
442
443/*
444 * XPath: /frr-ripngd:ripngd/instance/static-route
445 */
446static int ripngd_instance_static_route_create(enum nb_event event,
447 const struct lyd_node *dnode,
448 union nb_resource *resource)
449{
521d1b12
RW
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
e9ce224b
RW
461 return NB_OK;
462}
463
464static int ripngd_instance_static_route_delete(enum nb_event event,
465 const struct lyd_node *dnode)
466{
521d1b12
RW
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
e9ce224b
RW
477 return NB_OK;
478}
479
480/*
481 * XPath: /frr-ripngd:ripngd/instance/aggregate-address
482 */
483static int
484ripngd_instance_aggregate_address_create(enum nb_event event,
485 const struct lyd_node *dnode,
486 union nb_resource *resource)
487{
6fc29385
RW
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
e9ce224b
RW
498 return NB_OK;
499}
500
501static int
502ripngd_instance_aggregate_address_delete(enum nb_event event,
503 const struct lyd_node *dnode)
504{
6fc29385
RW
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
e9ce224b
RW
515 return NB_OK;
516}
517
f8981ec5
RW
518/*
519 * XPath: /frr-ripngd:ripngd/instance/timers
520 */
521static 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
e9ce224b
RW
527/*
528 * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
529 */
530static int
531ripngd_instance_timers_flush_interval_modify(enum nb_event event,
532 const struct lyd_node *dnode,
533 union nb_resource *resource)
534{
f8981ec5
RW
535 if (event != NB_EV_APPLY)
536 return NB_OK;
537
538 ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
539
e9ce224b
RW
540 return NB_OK;
541}
542
543/*
544 * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
545 */
546static int
547ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
548 const struct lyd_node *dnode,
549 union nb_resource *resource)
550{
f8981ec5
RW
551 if (event != NB_EV_APPLY)
552 return NB_OK;
553
554 ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
555
e9ce224b
RW
556 return NB_OK;
557}
558
559/*
560 * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
561 */
562static int
563ripngd_instance_timers_update_interval_modify(enum nb_event event,
564 const struct lyd_node *dnode,
565 union nb_resource *resource)
566{
f8981ec5
RW
567 if (event != NB_EV_APPLY)
568 return NB_OK;
569
570 ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
571
e9ce224b
RW
572 return NB_OK;
573}
574
575/*
576 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor
577 */
578static const void *
579ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
580 const void *list_entry)
581{
a8bf8fb8
RW
582 struct listnode *node;
583
584 if (list_entry == NULL)
585 node = listhead(peer_list);
586 else
587 node = listnextnode((struct listnode *)list_entry);
588
589 return node;
e9ce224b
RW
590}
591
592static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
593 struct yang_list_keys *keys)
594{
a8bf8fb8
RW
595 const struct listnode *node = list_entry;
596 const struct ripng_peer *peer = listgetdata(node);
597
598 keys->num = 1;
599 (void)inet_ntop(AF_INET6, &peer->addr, keys->key[0],
600 sizeof(keys->key[0]));
601
e9ce224b
RW
602 return NB_OK;
603}
604
605static const void *
606ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
607 const struct yang_list_keys *keys)
608{
a8bf8fb8
RW
609 struct in6_addr address;
610 struct ripng_peer *peer;
611 struct listnode *node;
612
613 yang_str2ipv6(keys->key[0], &address);
614
615 for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) {
616 if (IPV6_ADDR_SAME(&peer->addr, &address))
617 return node;
618 }
619
e9ce224b
RW
620 return NULL;
621}
622
623/*
624 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/address
625 */
626static struct yang_data *
627ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath,
628 const void *list_entry)
629{
a8bf8fb8
RW
630 const struct listnode *node = list_entry;
631 const struct ripng_peer *peer = listgetdata(node);
632
633 return yang_data_new_ipv6(xpath, &peer->addr);
e9ce224b
RW
634}
635
636/*
637 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/last-update
638 */
639static struct yang_data *
640ripngd_state_neighbors_neighbor_last_update_get_elem(const char *xpath,
641 const void *list_entry)
642{
a8bf8fb8 643 /* TODO: yang:date-and-time is tricky */
e9ce224b
RW
644 return NULL;
645}
646
647/*
648 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd
649 */
650static struct yang_data *
651ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
652 const char *xpath, const void *list_entry)
653{
a8bf8fb8
RW
654 const struct listnode *node = list_entry;
655 const struct ripng_peer *peer = listgetdata(node);
656
657 return yang_data_new_uint32(xpath, peer->recv_badpackets);
e9ce224b
RW
658}
659
660/*
661 * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd
662 */
663static struct yang_data *
664ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
665 const void *list_entry)
666{
a8bf8fb8
RW
667 const struct listnode *node = list_entry;
668 const struct ripng_peer *peer = listgetdata(node);
669
670 return yang_data_new_uint32(xpath, peer->recv_badroutes);
e9ce224b
RW
671}
672
673/*
674 * XPath: /frr-ripngd:ripngd/state/routes/route
675 */
676static const void *
677ripngd_state_routes_route_get_next(const void *parent_list_entry,
678 const void *list_entry)
679{
5707da09
RW
680 struct agg_node *rn;
681
682 if (ripng == NULL)
683 return NULL;
684
685 if (list_entry == NULL)
686 rn = agg_route_top(ripng->table);
687 else
688 rn = agg_route_next((struct agg_node *)list_entry);
689 while (rn && rn->info == NULL)
690 rn = agg_route_next(rn);
691
692 return rn;
e9ce224b
RW
693}
694
695static int ripngd_state_routes_route_get_keys(const void *list_entry,
696 struct yang_list_keys *keys)
697{
5707da09
RW
698 const struct agg_node *rn = list_entry;
699
700 keys->num = 1;
701 (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0]));
702
e9ce224b
RW
703 return NB_OK;
704}
705
706static const void *
707ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
708 const struct yang_list_keys *keys)
709{
5707da09
RW
710 struct prefix prefix;
711 struct agg_node *rn;
712
713 yang_str2ipv6p(keys->key[0], &prefix);
714
715 rn = agg_node_lookup(ripng->table, &prefix);
716 if (!rn || !rn->info)
717 return NULL;
718
719 agg_unlock_node(rn);
720
721 return rn;
e9ce224b
RW
722}
723
724/*
725 * XPath: /frr-ripngd:ripngd/state/routes/route/prefix
726 */
727static struct yang_data *
728ripngd_state_routes_route_prefix_get_elem(const char *xpath,
729 const void *list_entry)
730{
5707da09
RW
731 const struct agg_node *rn = list_entry;
732 const struct ripng_info *rinfo = listnode_head(rn->info);
733
734 return yang_data_new_ipv6p(xpath, &rinfo->rp->p);
e9ce224b
RW
735}
736
737/*
738 * XPath: /frr-ripngd:ripngd/state/routes/route/next-hop
739 */
740static struct yang_data *
741ripngd_state_routes_route_next_hop_get_elem(const char *xpath,
742 const void *list_entry)
743{
5707da09
RW
744 const struct agg_node *rn = list_entry;
745 const struct ripng_info *rinfo = listnode_head(rn->info);
746
747 return yang_data_new_ipv6(xpath, &rinfo->nexthop);
e9ce224b
RW
748}
749
750/*
751 * XPath: /frr-ripngd:ripngd/state/routes/route/interface
752 */
753static struct yang_data *
754ripngd_state_routes_route_interface_get_elem(const char *xpath,
755 const void *list_entry)
756{
5707da09
RW
757 const struct agg_node *rn = list_entry;
758 const struct ripng_info *rinfo = listnode_head(rn->info);
759
760 return yang_data_new_string(
761 xpath, ifindex2ifname(rinfo->ifindex, VRF_DEFAULT));
e9ce224b
RW
762}
763
764/*
765 * XPath: /frr-ripngd:ripngd/state/routes/route/metric
766 */
767static struct yang_data *
768ripngd_state_routes_route_metric_get_elem(const char *xpath,
769 const void *list_entry)
770{
5707da09
RW
771 const struct agg_node *rn = list_entry;
772 const struct ripng_info *rinfo = listnode_head(rn->info);
773
774 return yang_data_new_uint8(xpath, rinfo->metric);
e9ce224b
RW
775}
776
777/*
778 * XPath: /frr-ripngd:clear-ripng-route
779 */
780static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
781 struct list *output)
782{
49e06d25
RW
783 struct agg_node *rp;
784 struct ripng_info *rinfo;
785 struct list *list;
786 struct listnode *listnode;
787
788 /* Clear received RIPng routes */
789 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
790 list = rp->info;
791 if (list == NULL)
792 continue;
793
794 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
795 if (!ripng_route_rte(rinfo))
796 continue;
797
798 if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
799 ripng_zebra_ipv6_delete(rp);
800 break;
801 }
802
803 if (rinfo) {
804 RIPNG_TIMER_OFF(rinfo->t_timeout);
805 RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
806 listnode_delete(list, rinfo);
807 ripng_info_free(rinfo);
808 }
809
810 if (list_isempty(list)) {
811 list_delete(&list);
812 rp->info = NULL;
813 agg_unlock_node(rp);
814 }
815 }
816
e9ce224b
RW
817 return NB_OK;
818}
819
820/*
821 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
822 */
823static int
824lib_interface_ripng_split_horizon_modify(enum nb_event event,
825 const struct lyd_node *dnode,
826 union nb_resource *resource)
827{
d406db4c
RW
828 struct interface *ifp;
829 struct ripng_interface *ri;
830
831 if (event != NB_EV_APPLY)
832 return NB_OK;
833
834 ifp = yang_dnode_get_entry(dnode, true);
835 ri = ifp->info;
836 ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
837
e9ce224b
RW
838 return NB_OK;
839}
840
841/* clang-format off */
842const struct frr_yang_module_info frr_ripngd_info = {
843 .name = "frr-ripngd",
844 .nodes = {
845 {
846 .xpath = "/frr-ripngd:ripngd/instance",
847 .cbs.create = ripngd_instance_create,
848 .cbs.delete = ripngd_instance_delete,
9a12e9e5 849 .cbs.cli_show = cli_show_router_ripng,
e9ce224b
RW
850 },
851 {
852 .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
853 .cbs.modify = ripngd_instance_allow_ecmp_modify,
1e42a07c 854 .cbs.cli_show = cli_show_ripng_allow_ecmp,
e9ce224b
RW
855 },
856 {
857 .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
858 .cbs.modify = ripngd_instance_default_information_originate_modify,
54b56562 859 .cbs.cli_show = cli_show_ripng_default_information_originate,
e9ce224b
RW
860 },
861 {
862 .xpath = "/frr-ripngd:ripngd/instance/default-metric",
863 .cbs.modify = ripngd_instance_default_metric_modify,
ad8778c0 864 .cbs.cli_show = cli_show_ripng_default_metric,
e9ce224b
RW
865 },
866 {
867 .xpath = "/frr-ripngd:ripngd/instance/network",
868 .cbs.create = ripngd_instance_network_create,
869 .cbs.delete = ripngd_instance_network_delete,
cc48702b 870 .cbs.cli_show = cli_show_ripng_network_prefix,
e9ce224b
RW
871 },
872 {
873 .xpath = "/frr-ripngd:ripngd/instance/interface",
874 .cbs.create = ripngd_instance_interface_create,
875 .cbs.delete = ripngd_instance_interface_delete,
cc48702b 876 .cbs.cli_show = cli_show_ripng_network_interface,
e9ce224b
RW
877 },
878 {
879 .xpath = "/frr-ripngd:ripngd/instance/offset-list",
880 .cbs.create = ripngd_instance_offset_list_create,
881 .cbs.delete = ripngd_instance_offset_list_delete,
b09956ca 882 .cbs.cli_show = cli_show_ripng_offset_list,
e9ce224b
RW
883 },
884 {
885 .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list",
886 .cbs.modify = ripngd_instance_offset_list_access_list_modify,
887 },
888 {
889 .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric",
890 .cbs.modify = ripngd_instance_offset_list_metric_modify,
891 },
892 {
893 .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
894 .cbs.create = ripngd_instance_passive_interface_create,
895 .cbs.delete = ripngd_instance_passive_interface_delete,
22e8c7ae 896 .cbs.cli_show = cli_show_ripng_passive_interface,
e9ce224b
RW
897 },
898 {
899 .xpath = "/frr-ripngd:ripngd/instance/redistribute",
900 .cbs.create = ripngd_instance_redistribute_create,
901 .cbs.delete = ripngd_instance_redistribute_delete,
db2038c7
RW
902 .cbs.apply_finish = ripngd_instance_redistribute_apply_finish,
903 .cbs.cli_show = cli_show_ripng_redistribute,
e9ce224b
RW
904 },
905 {
906 .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
907 .cbs.modify = ripngd_instance_redistribute_route_map_modify,
908 .cbs.delete = ripngd_instance_redistribute_route_map_delete,
909 },
910 {
911 .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
912 .cbs.modify = ripngd_instance_redistribute_metric_modify,
913 .cbs.delete = ripngd_instance_redistribute_metric_delete,
914 },
915 {
916 .xpath = "/frr-ripngd:ripngd/instance/static-route",
917 .cbs.create = ripngd_instance_static_route_create,
918 .cbs.delete = ripngd_instance_static_route_delete,
521d1b12 919 .cbs.cli_show = cli_show_ripng_route,
e9ce224b
RW
920 },
921 {
922 .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
923 .cbs.create = ripngd_instance_aggregate_address_create,
924 .cbs.delete = ripngd_instance_aggregate_address_delete,
6fc29385 925 .cbs.cli_show = cli_show_ripng_aggregate_address,
e9ce224b 926 },
f8981ec5
RW
927 {
928 .xpath = "/frr-ripngd:ripngd/instance/timers",
929 .cbs.apply_finish = ripngd_instance_timers_apply_finish,
930 .cbs.cli_show = cli_show_ripng_timers,
931 },
e9ce224b
RW
932 {
933 .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval",
934 .cbs.modify = ripngd_instance_timers_flush_interval_modify,
935 },
936 {
937 .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval",
938 .cbs.modify = ripngd_instance_timers_holddown_interval_modify,
939 },
940 {
941 .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval",
942 .cbs.modify = ripngd_instance_timers_update_interval_modify,
943 },
944 {
945 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor",
946 .cbs.get_next = ripngd_state_neighbors_neighbor_get_next,
947 .cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys,
948 .cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry,
949 },
950 {
951 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address",
952 .cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem,
953 },
954 {
955 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update",
956 .cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem,
957 },
958 {
959 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd",
960 .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
961 },
962 {
963 .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd",
964 .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
965 },
966 {
967 .xpath = "/frr-ripngd:ripngd/state/routes/route",
968 .cbs.get_next = ripngd_state_routes_route_get_next,
969 .cbs.get_keys = ripngd_state_routes_route_get_keys,
970 .cbs.lookup_entry = ripngd_state_routes_route_lookup_entry,
971 },
972 {
973 .xpath = "/frr-ripngd:ripngd/state/routes/route/prefix",
974 .cbs.get_elem = ripngd_state_routes_route_prefix_get_elem,
975 },
976 {
977 .xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop",
978 .cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem,
979 },
980 {
981 .xpath = "/frr-ripngd:ripngd/state/routes/route/interface",
982 .cbs.get_elem = ripngd_state_routes_route_interface_get_elem,
983 },
984 {
985 .xpath = "/frr-ripngd:ripngd/state/routes/route/metric",
986 .cbs.get_elem = ripngd_state_routes_route_metric_get_elem,
987 },
988 {
989 .xpath = "/frr-ripngd:clear-ripng-route",
990 .cbs.rpc = clear_ripng_route_rpc,
991 },
992 {
993 .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
994 .cbs.modify = lib_interface_ripng_split_horizon_modify,
d406db4c 995 .cbs.cli_show = cli_show_ipv6_ripng_split_horizon,
e9ce224b
RW
996 },
997 {
998 .xpath = NULL,
999 },
1000 }
1001};