]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_nb_config.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / ripngd / ripng_nb_config.c
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 */
31 int 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
78 int 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
91 const 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
103 int 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
114 const 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 */
124 int 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 */
147 int 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 */
175 int 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 */
191 int 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
206 int 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 */
224 int 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
238 int 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 */
255 int 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
273 int 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 */
298 int 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 */
322 int 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 */
343 int 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
357 int 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 */
374 int 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
390 int 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
416 void 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 */
432 int 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
454 int 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 */
476 int 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
495 int 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 */
515 int 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
522 int 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
542 static 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 */
552 int 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
563 int 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 */
577 int 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
588 int 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 */
602 int 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
620 int 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 */
641 int 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
658 int 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 */
678 void 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 */
691 int 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 */
707 int 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 */
724 int 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 */
741 int 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 }