]> git.proxmox.com Git - mirror_frr.git/blame_incremental - ripngd/ripng_nb_config.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / ripngd / ripng_nb_config.c
... / ...
CommitLineData
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 1998 Kunihiro Ishiguro
4 * Copyright (C) 2018 NetDEF, Inc.
5 * Renato Westphal
6 * Copyright (C) 2023 LabN Consulting, L.L.C.
7 */
8
9#include <zebra.h>
10
11#include "if.h"
12#include "vrf.h"
13#include "log.h"
14#include "prefix.h"
15#include "table.h"
16#include "command.h"
17#include "if_rmap.h"
18#include "routemap.h"
19#include "agg_table.h"
20#include "northbound.h"
21#include "libfrr.h"
22
23#include "ripngd/ripngd.h"
24#include "ripngd/ripng_nb.h"
25#include "ripngd/ripng_debug.h"
26#include "ripngd/ripng_route.h"
27
28/*
29 * XPath: /frr-ripngd:ripngd/instance
30 */
31int ripngd_instance_create(struct nb_cb_create_args *args)
32{
33 struct ripng *ripng;
34 struct vrf *vrf;
35 const char *vrf_name;
36 int socket;
37
38 vrf_name = yang_dnode_get_string(args->dnode, "./vrf");
39 vrf = vrf_lookup_by_name(vrf_name);
40
41 /*
42 * Try to create a RIPng socket only if the VRF is enabled, otherwise
43 * create a disabled RIPng instance and wait for the VRF to be enabled.
44 */
45 switch (args->event) {
46 case NB_EV_VALIDATE:
47 break;
48 case NB_EV_PREPARE:
49 if (!vrf || !vrf_is_enabled(vrf))
50 break;
51
52 socket = ripng_make_socket(vrf);
53 if (socket < 0)
54 return NB_ERR_RESOURCE;
55 args->resource->fd = socket;
56 break;
57 case NB_EV_ABORT:
58 if (!vrf || !vrf_is_enabled(vrf))
59 break;
60
61 socket = args->resource->fd;
62 close(socket);
63 break;
64 case NB_EV_APPLY:
65 if (vrf && vrf_is_enabled(vrf))
66 socket = args->resource->fd;
67 else
68 socket = -1;
69
70 ripng = ripng_create(vrf_name, vrf, socket);
71 nb_running_set_entry(args->dnode, ripng);
72 break;
73 }
74
75 return NB_OK;
76}
77
78int ripngd_instance_destroy(struct nb_cb_destroy_args *args)
79{
80 struct ripng *ripng;
81
82 if (args->event != NB_EV_APPLY)
83 return NB_OK;
84
85 ripng = nb_running_unset_entry(args->dnode);
86 ripng_clean(ripng);
87
88 return NB_OK;
89}
90
91const void *ripngd_instance_get_next(struct nb_cb_get_next_args *args)
92{
93 struct ripng *ripng = (struct ripng *)args->list_entry;
94
95 if (args->list_entry == NULL)
96 ripng = RB_MIN(ripng_instance_head, &ripng_instances);
97 else
98 ripng = RB_NEXT(ripng_instance_head, ripng);
99
100 return ripng;
101}
102
103int ripngd_instance_get_keys(struct nb_cb_get_keys_args *args)
104{
105 const struct ripng *ripng = args->list_entry;
106
107 args->keys->num = 1;
108 strlcpy(args->keys->key[0], ripng->vrf_name,
109 sizeof(args->keys->key[0]));
110
111 return NB_OK;
112}
113
114const void *ripngd_instance_lookup_entry(struct nb_cb_lookup_entry_args *args)
115{
116 const char *vrf_name = args->keys->key[0];
117
118 return ripng_lookup_by_vrf_name(vrf_name);
119}
120
121/*
122 * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
123 */
124int ripngd_instance_allow_ecmp_modify(struct nb_cb_modify_args *args)
125{
126 struct ripng *ripng;
127
128 if (args->event != NB_EV_APPLY)
129 return NB_OK;
130
131 ripng = nb_running_get_entry(args->dnode, NULL, true);
132 ripng->ecmp =
133 MIN(yang_dnode_get_uint8(args->dnode, NULL), zebra_ecmp_count);
134 if (!ripng->ecmp) {
135 ripng_ecmp_disable(ripng);
136 return NB_OK;
137 }
138
139 ripng_ecmp_change(ripng);
140
141 return NB_OK;
142}
143
144/*
145 * XPath: /frr-ripngd:ripngd/instance/default-information-originate
146 */
147int ripngd_instance_default_information_originate_modify(
148 struct nb_cb_modify_args *args)
149{
150 struct ripng *ripng;
151 bool default_information;
152 struct prefix_ipv6 p;
153
154 if (args->event != NB_EV_APPLY)
155 return NB_OK;
156
157 ripng = nb_running_get_entry(args->dnode, NULL, true);
158 default_information = yang_dnode_get_bool(args->dnode, NULL);
159
160 (void)str2prefix_ipv6("::/0", &p);
161 if (default_information) {
162 ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
163 RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
164 } else {
165 ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
166 RIPNG_ROUTE_DEFAULT, &p, 0);
167 }
168
169 return NB_OK;
170}
171
172/*
173 * XPath: /frr-ripngd:ripngd/instance/default-metric
174 */
175int ripngd_instance_default_metric_modify(struct nb_cb_modify_args *args)
176{
177 struct ripng *ripng;
178
179 if (args->event != NB_EV_APPLY)
180 return NB_OK;
181
182 ripng = nb_running_get_entry(args->dnode, NULL, true);
183 ripng->default_metric = yang_dnode_get_uint8(args->dnode, NULL);
184
185 return NB_OK;
186}
187
188/*
189 * XPath: /frr-ripngd:ripngd/instance/network
190 */
191int ripngd_instance_network_create(struct nb_cb_create_args *args)
192{
193 struct ripng *ripng;
194 struct prefix p;
195
196 if (args->event != NB_EV_APPLY)
197 return NB_OK;
198
199 ripng = nb_running_get_entry(args->dnode, NULL, true);
200 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
201 apply_mask_ipv6((struct prefix_ipv6 *)&p);
202
203 return ripng_enable_network_add(ripng, &p);
204}
205
206int ripngd_instance_network_destroy(struct nb_cb_destroy_args *args)
207{
208 struct ripng *ripng;
209 struct prefix p;
210
211 if (args->event != NB_EV_APPLY)
212 return NB_OK;
213
214 ripng = nb_running_get_entry(args->dnode, NULL, true);
215 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
216 apply_mask_ipv6((struct prefix_ipv6 *)&p);
217
218 return ripng_enable_network_delete(ripng, &p);
219}
220
221/*
222 * XPath: /frr-ripngd:ripngd/instance/interface
223 */
224int ripngd_instance_interface_create(struct nb_cb_create_args *args)
225{
226 struct ripng *ripng;
227 const char *ifname;
228
229 if (args->event != NB_EV_APPLY)
230 return NB_OK;
231
232 ripng = nb_running_get_entry(args->dnode, NULL, true);
233 ifname = yang_dnode_get_string(args->dnode, NULL);
234
235 return ripng_enable_if_add(ripng, ifname);
236}
237
238int ripngd_instance_interface_destroy(struct nb_cb_destroy_args *args)
239{
240 struct ripng *ripng;
241 const char *ifname;
242
243 if (args->event != NB_EV_APPLY)
244 return NB_OK;
245
246 ripng = nb_running_get_entry(args->dnode, NULL, true);
247 ifname = yang_dnode_get_string(args->dnode, NULL);
248
249 return ripng_enable_if_delete(ripng, ifname);
250}
251
252/*
253 * XPath: /frr-ripngd:ripngd/instance/offset-list
254 */
255int ripngd_instance_offset_list_create(struct nb_cb_create_args *args)
256{
257 struct ripng *ripng;
258 const char *ifname;
259 struct ripng_offset_list *offset;
260
261 if (args->event != NB_EV_APPLY)
262 return NB_OK;
263
264 ripng = nb_running_get_entry(args->dnode, NULL, true);
265 ifname = yang_dnode_get_string(args->dnode, "./interface");
266
267 offset = ripng_offset_list_new(ripng, ifname);
268 nb_running_set_entry(args->dnode, offset);
269
270 return NB_OK;
271}
272
273int ripngd_instance_offset_list_destroy(struct nb_cb_destroy_args *args)
274{
275 int direct;
276 struct ripng_offset_list *offset;
277
278 if (args->event != NB_EV_APPLY)
279 return NB_OK;
280
281 direct = yang_dnode_get_enum(args->dnode, "./direction");
282
283 offset = nb_running_unset_entry(args->dnode);
284 if (offset->direct[direct].alist_name) {
285 free(offset->direct[direct].alist_name);
286 offset->direct[direct].alist_name = NULL;
287 }
288 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
289 && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
290 ripng_offset_list_del(offset);
291
292 return NB_OK;
293}
294
295/*
296 * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
297 */
298int ripngd_instance_offset_list_access_list_modify(
299 struct nb_cb_modify_args *args)
300{
301 int direct;
302 struct ripng_offset_list *offset;
303 const char *alist_name;
304
305 if (args->event != NB_EV_APPLY)
306 return NB_OK;
307
308 direct = yang_dnode_get_enum(args->dnode, "../direction");
309 alist_name = yang_dnode_get_string(args->dnode, NULL);
310
311 offset = nb_running_get_entry(args->dnode, NULL, true);
312 if (offset->direct[direct].alist_name)
313 free(offset->direct[direct].alist_name);
314 offset->direct[direct].alist_name = strdup(alist_name);
315
316 return NB_OK;
317}
318
319/*
320 * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
321 */
322int ripngd_instance_offset_list_metric_modify(struct nb_cb_modify_args *args)
323{
324 int direct;
325 uint8_t metric;
326 struct ripng_offset_list *offset;
327
328 if (args->event != NB_EV_APPLY)
329 return NB_OK;
330
331 direct = yang_dnode_get_enum(args->dnode, "../direction");
332 metric = yang_dnode_get_uint8(args->dnode, NULL);
333
334 offset = nb_running_get_entry(args->dnode, NULL, true);
335 offset->direct[direct].metric = metric;
336
337 return NB_OK;
338}
339
340/*
341 * XPath: /frr-ripngd:ripngd/instance/passive-interface
342 */
343int ripngd_instance_passive_interface_create(struct nb_cb_create_args *args)
344{
345 struct ripng *ripng;
346 const char *ifname;
347
348 if (args->event != NB_EV_APPLY)
349 return NB_OK;
350
351 ripng = nb_running_get_entry(args->dnode, NULL, true);
352 ifname = yang_dnode_get_string(args->dnode, NULL);
353
354 return ripng_passive_interface_set(ripng, ifname);
355}
356
357int ripngd_instance_passive_interface_destroy(struct nb_cb_destroy_args *args)
358{
359 struct ripng *ripng;
360 const char *ifname;
361
362 if (args->event != NB_EV_APPLY)
363 return NB_OK;
364
365 ripng = nb_running_get_entry(args->dnode, NULL, true);
366 ifname = yang_dnode_get_string(args->dnode, NULL);
367
368 return ripng_passive_interface_unset(ripng, ifname);
369}
370
371/*
372 * XPath: /frr-ripngd:ripngd/instance/redistribute
373 */
374int ripngd_instance_redistribute_create(struct nb_cb_create_args *args)
375{
376 struct ripng *ripng;
377 int type;
378
379 if (args->event != NB_EV_APPLY)
380 return NB_OK;
381
382 ripng = nb_running_get_entry(args->dnode, NULL, true);
383 type = yang_dnode_get_enum(args->dnode, "./protocol");
384
385 ripng->redist[type].enabled = true;
386
387 return NB_OK;
388}
389
390int ripngd_instance_redistribute_destroy(struct nb_cb_destroy_args *args)
391{
392 struct ripng *ripng;
393 int type;
394
395 if (args->event != NB_EV_APPLY)
396 return NB_OK;
397
398 ripng = nb_running_get_entry(args->dnode, NULL, true);
399 type = yang_dnode_get_enum(args->dnode, "./protocol");
400
401 ripng->redist[type].enabled = false;
402 if (ripng->redist[type].route_map.name) {
403 free(ripng->redist[type].route_map.name);
404 ripng->redist[type].route_map.name = NULL;
405 ripng->redist[type].route_map.map = NULL;
406 }
407 ripng->redist[type].metric_config = false;
408 ripng->redist[type].metric = 0;
409
410 if (ripng->enabled)
411 ripng_redistribute_conf_delete(ripng, type);
412
413 return NB_OK;
414}
415
416void ripngd_instance_redistribute_apply_finish(
417 struct nb_cb_apply_finish_args *args)
418{
419 struct ripng *ripng;
420 int type;
421
422 ripng = nb_running_get_entry(args->dnode, NULL, true);
423 type = yang_dnode_get_enum(args->dnode, "./protocol");
424
425 if (ripng->enabled)
426 ripng_redistribute_conf_update(ripng, type);
427}
428
429/*
430 * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
431 */
432int ripngd_instance_redistribute_route_map_modify(
433 struct nb_cb_modify_args *args)
434{
435 struct ripng *ripng;
436 int type;
437 const char *rmap_name;
438
439 if (args->event != NB_EV_APPLY)
440 return NB_OK;
441
442 ripng = nb_running_get_entry(args->dnode, NULL, true);
443 type = yang_dnode_get_enum(args->dnode, "../protocol");
444 rmap_name = yang_dnode_get_string(args->dnode, NULL);
445
446 if (ripng->redist[type].route_map.name)
447 free(ripng->redist[type].route_map.name);
448 ripng->redist[type].route_map.name = strdup(rmap_name);
449 ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
450
451 return NB_OK;
452}
453
454int ripngd_instance_redistribute_route_map_destroy(
455 struct nb_cb_destroy_args *args)
456{
457 struct ripng *ripng;
458 int type;
459
460 if (args->event != NB_EV_APPLY)
461 return NB_OK;
462
463 ripng = nb_running_get_entry(args->dnode, NULL, true);
464 type = yang_dnode_get_enum(args->dnode, "../protocol");
465
466 free(ripng->redist[type].route_map.name);
467 ripng->redist[type].route_map.name = NULL;
468 ripng->redist[type].route_map.map = NULL;
469
470 return NB_OK;
471}
472
473/*
474 * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
475 */
476int ripngd_instance_redistribute_metric_modify(struct nb_cb_modify_args *args)
477{
478 struct ripng *ripng;
479 int type;
480 uint8_t metric;
481
482 if (args->event != NB_EV_APPLY)
483 return NB_OK;
484
485 ripng = nb_running_get_entry(args->dnode, NULL, true);
486 type = yang_dnode_get_enum(args->dnode, "../protocol");
487 metric = yang_dnode_get_uint8(args->dnode, NULL);
488
489 ripng->redist[type].metric_config = true;
490 ripng->redist[type].metric = metric;
491
492 return NB_OK;
493}
494
495int ripngd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args)
496{
497 struct ripng *ripng;
498 int type;
499
500 if (args->event != NB_EV_APPLY)
501 return NB_OK;
502
503 ripng = nb_running_get_entry(args->dnode, NULL, true);
504 type = yang_dnode_get_enum(args->dnode, "../protocol");
505
506 ripng->redist[type].metric_config = false;
507 ripng->redist[type].metric = 0;
508
509 return NB_OK;
510}
511
512/*
513 * XPath: /frr-ripngd:ripngd/instance/if-route-maps/if-route-map
514 */
515int ripngd_instance_if_route_maps_if_route_map_create(
516 struct nb_cb_create_args *args)
517{
518 /* if_rmap is created when first routemap is added */
519 return NB_OK;
520}
521
522int ripngd_instance_if_route_maps_if_route_map_destroy(
523 struct nb_cb_destroy_args *args)
524{
525 struct ripng *ripng;
526
527 if (args->event != NB_EV_APPLY)
528 return NB_OK;
529
530 /*
531 * YANG will prune edit deletes up to the most general deleted node so
532 * we need to handle deleting any existing state underneath and not
533 * count on those more specific callbacks being called individually.
534 */
535
536 ripng = nb_running_get_entry(args->dnode, NULL, true);
537 if_rmap_yang_destroy_cb(ripng->if_rmap_ctx, args->dnode);
538
539 return NB_OK;
540}
541
542static void if_route_map_modify(const struct lyd_node *dnode,
543 enum if_rmap_type type, bool delete)
544{
545 struct ripng *ripng = nb_running_get_entry(dnode, NULL, true);
546
547 if_rmap_yang_modify_cb(ripng->if_rmap_ctx, dnode, type, delete);
548}
549/*
550 * XPath: /frr-ripng:ripng/instance/if-route-maps/if-route-map/in-route-map
551 */
552int ripngd_instance_if_route_maps_if_route_map_in_route_map_modify(
553 struct nb_cb_modify_args *args)
554{
555 if (args->event != NB_EV_APPLY)
556 return NB_OK;
557
558 if_route_map_modify(args->dnode, IF_RMAP_IN, false);
559
560 return NB_OK;
561}
562
563int ripngd_instance_if_route_maps_if_route_map_in_route_map_destroy(
564 struct nb_cb_destroy_args *args)
565{
566 if (args->event != NB_EV_APPLY)
567 return NB_OK;
568
569 if_route_map_modify(args->dnode, IF_RMAP_IN, true);
570
571 return NB_OK;
572}
573
574/*
575 * XPath: /frr-ripngd:ripngd/instance/if-route-maps/if-route-map/out-route-map
576 */
577int ripngd_instance_if_route_maps_if_route_map_out_route_map_modify(
578 struct nb_cb_modify_args *args)
579{
580 if (args->event != NB_EV_APPLY)
581 return NB_OK;
582
583 if_route_map_modify(args->dnode, IF_RMAP_OUT, false);
584
585 return NB_OK;
586}
587
588int ripngd_instance_if_route_maps_if_route_map_out_route_map_destroy(
589 struct nb_cb_destroy_args *args)
590{
591 if (args->event != NB_EV_APPLY)
592 return NB_OK;
593
594 if_route_map_modify(args->dnode, IF_RMAP_OUT, true);
595
596 return NB_OK;
597}
598
599/*
600 * XPath: /frr-ripngd:ripngd/instance/static-route
601 */
602int ripngd_instance_static_route_create(struct nb_cb_create_args *args)
603{
604 struct ripng *ripng;
605 struct prefix_ipv6 p;
606
607 if (args->event != NB_EV_APPLY)
608 return NB_OK;
609
610 ripng = nb_running_get_entry(args->dnode, NULL, true);
611 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
612 apply_mask_ipv6(&p);
613
614 ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
615 0, NULL, 0);
616
617 return NB_OK;
618}
619
620int ripngd_instance_static_route_destroy(struct nb_cb_destroy_args *args)
621{
622 struct ripng *ripng;
623 struct prefix_ipv6 p;
624
625 if (args->event != NB_EV_APPLY)
626 return NB_OK;
627
628 ripng = nb_running_get_entry(args->dnode, NULL, true);
629 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
630 apply_mask_ipv6(&p);
631
632 ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
633 &p, 0);
634
635 return NB_OK;
636}
637
638/*
639 * XPath: /frr-ripngd:ripngd/instance/aggregate-address
640 */
641int ripngd_instance_aggregate_address_create(struct nb_cb_create_args *args)
642{
643 struct ripng *ripng;
644 struct prefix_ipv6 p;
645
646 if (args->event != NB_EV_APPLY)
647 return NB_OK;
648
649 ripng = nb_running_get_entry(args->dnode, NULL, true);
650 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
651 apply_mask_ipv6(&p);
652
653 ripng_aggregate_add(ripng, (struct prefix *)&p);
654
655 return NB_OK;
656}
657
658int ripngd_instance_aggregate_address_destroy(struct nb_cb_destroy_args *args)
659{
660 struct ripng *ripng;
661 struct prefix_ipv6 p;
662
663 if (args->event != NB_EV_APPLY)
664 return NB_OK;
665
666 ripng = nb_running_get_entry(args->dnode, NULL, true);
667 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
668 apply_mask_ipv6(&p);
669
670 ripng_aggregate_delete(ripng, (struct prefix *)&p);
671
672 return NB_OK;
673}
674
675/*
676 * XPath: /frr-ripngd:ripngd/instance/timers
677 */
678void ripngd_instance_timers_apply_finish(struct nb_cb_apply_finish_args *args)
679{
680 struct ripng *ripng;
681
682 ripng = nb_running_get_entry(args->dnode, NULL, true);
683
684 /* Reset update timer thread. */
685 ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
686}
687
688/*
689 * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
690 */
691int ripngd_instance_timers_flush_interval_modify(struct nb_cb_modify_args *args)
692{
693 struct ripng *ripng;
694
695 if (args->event != NB_EV_APPLY)
696 return NB_OK;
697
698 ripng = nb_running_get_entry(args->dnode, NULL, true);
699 ripng->garbage_time = yang_dnode_get_uint16(args->dnode, NULL);
700
701 return NB_OK;
702}
703
704/*
705 * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
706 */
707int ripngd_instance_timers_holddown_interval_modify(
708 struct nb_cb_modify_args *args)
709{
710 struct ripng *ripng;
711
712 if (args->event != NB_EV_APPLY)
713 return NB_OK;
714
715 ripng = nb_running_get_entry(args->dnode, NULL, true);
716 ripng->timeout_time = yang_dnode_get_uint16(args->dnode, NULL);
717
718 return NB_OK;
719}
720
721/*
722 * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
723 */
724int ripngd_instance_timers_update_interval_modify(
725 struct nb_cb_modify_args *args)
726{
727 struct ripng *ripng;
728
729 if (args->event != NB_EV_APPLY)
730 return NB_OK;
731
732 ripng = nb_running_get_entry(args->dnode, NULL, true);
733 ripng->update_time = yang_dnode_get_uint16(args->dnode, NULL);
734
735 return NB_OK;
736}
737
738/*
739 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
740 */
741int lib_interface_ripng_split_horizon_modify(struct nb_cb_modify_args *args)
742{
743 struct interface *ifp;
744 struct ripng_interface *ri;
745
746 if (args->event != NB_EV_APPLY)
747 return NB_OK;
748
749 ifp = nb_running_get_entry(args->dnode, NULL, true);
750 ri = ifp->info;
751 ri->split_horizon = yang_dnode_get_enum(args->dnode, NULL);
752
753 return NB_OK;
754}