]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_nb_config.c
bgpd: encode_label call, remove unnecessary braces
[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 = yang_dnode_get_bool(args->dnode, NULL);
133 if (!ripng->ecmp)
134 ripng_ecmp_disable(ripng);
135
136 return NB_OK;
137 }
138
139 /*
140 * XPath: /frr-ripngd:ripngd/instance/default-information-originate
141 */
142 int ripngd_instance_default_information_originate_modify(
143 struct nb_cb_modify_args *args)
144 {
145 struct ripng *ripng;
146 bool default_information;
147 struct prefix_ipv6 p;
148
149 if (args->event != NB_EV_APPLY)
150 return NB_OK;
151
152 ripng = nb_running_get_entry(args->dnode, NULL, true);
153 default_information = yang_dnode_get_bool(args->dnode, NULL);
154
155 (void)str2prefix_ipv6("::/0", &p);
156 if (default_information) {
157 ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
158 RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
159 } else {
160 ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
161 RIPNG_ROUTE_DEFAULT, &p, 0);
162 }
163
164 return NB_OK;
165 }
166
167 /*
168 * XPath: /frr-ripngd:ripngd/instance/default-metric
169 */
170 int ripngd_instance_default_metric_modify(struct nb_cb_modify_args *args)
171 {
172 struct ripng *ripng;
173
174 if (args->event != NB_EV_APPLY)
175 return NB_OK;
176
177 ripng = nb_running_get_entry(args->dnode, NULL, true);
178 ripng->default_metric = yang_dnode_get_uint8(args->dnode, NULL);
179
180 return NB_OK;
181 }
182
183 /*
184 * XPath: /frr-ripngd:ripngd/instance/network
185 */
186 int ripngd_instance_network_create(struct nb_cb_create_args *args)
187 {
188 struct ripng *ripng;
189 struct prefix p;
190
191 if (args->event != NB_EV_APPLY)
192 return NB_OK;
193
194 ripng = nb_running_get_entry(args->dnode, NULL, true);
195 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
196 apply_mask_ipv6((struct prefix_ipv6 *)&p);
197
198 return ripng_enable_network_add(ripng, &p);
199 }
200
201 int ripngd_instance_network_destroy(struct nb_cb_destroy_args *args)
202 {
203 struct ripng *ripng;
204 struct prefix p;
205
206 if (args->event != NB_EV_APPLY)
207 return NB_OK;
208
209 ripng = nb_running_get_entry(args->dnode, NULL, true);
210 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
211 apply_mask_ipv6((struct prefix_ipv6 *)&p);
212
213 return ripng_enable_network_delete(ripng, &p);
214 }
215
216 /*
217 * XPath: /frr-ripngd:ripngd/instance/interface
218 */
219 int ripngd_instance_interface_create(struct nb_cb_create_args *args)
220 {
221 struct ripng *ripng;
222 const char *ifname;
223
224 if (args->event != NB_EV_APPLY)
225 return NB_OK;
226
227 ripng = nb_running_get_entry(args->dnode, NULL, true);
228 ifname = yang_dnode_get_string(args->dnode, NULL);
229
230 return ripng_enable_if_add(ripng, ifname);
231 }
232
233 int ripngd_instance_interface_destroy(struct nb_cb_destroy_args *args)
234 {
235 struct ripng *ripng;
236 const char *ifname;
237
238 if (args->event != NB_EV_APPLY)
239 return NB_OK;
240
241 ripng = nb_running_get_entry(args->dnode, NULL, true);
242 ifname = yang_dnode_get_string(args->dnode, NULL);
243
244 return ripng_enable_if_delete(ripng, ifname);
245 }
246
247 /*
248 * XPath: /frr-ripngd:ripngd/instance/offset-list
249 */
250 int ripngd_instance_offset_list_create(struct nb_cb_create_args *args)
251 {
252 struct ripng *ripng;
253 const char *ifname;
254 struct ripng_offset_list *offset;
255
256 if (args->event != NB_EV_APPLY)
257 return NB_OK;
258
259 ripng = nb_running_get_entry(args->dnode, NULL, true);
260 ifname = yang_dnode_get_string(args->dnode, "./interface");
261
262 offset = ripng_offset_list_new(ripng, ifname);
263 nb_running_set_entry(args->dnode, offset);
264
265 return NB_OK;
266 }
267
268 int ripngd_instance_offset_list_destroy(struct nb_cb_destroy_args *args)
269 {
270 int direct;
271 struct ripng_offset_list *offset;
272
273 if (args->event != NB_EV_APPLY)
274 return NB_OK;
275
276 direct = yang_dnode_get_enum(args->dnode, "./direction");
277
278 offset = nb_running_unset_entry(args->dnode);
279 if (offset->direct[direct].alist_name) {
280 free(offset->direct[direct].alist_name);
281 offset->direct[direct].alist_name = NULL;
282 }
283 if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
284 && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
285 ripng_offset_list_del(offset);
286
287 return NB_OK;
288 }
289
290 /*
291 * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
292 */
293 int ripngd_instance_offset_list_access_list_modify(
294 struct nb_cb_modify_args *args)
295 {
296 int direct;
297 struct ripng_offset_list *offset;
298 const char *alist_name;
299
300 if (args->event != NB_EV_APPLY)
301 return NB_OK;
302
303 direct = yang_dnode_get_enum(args->dnode, "../direction");
304 alist_name = yang_dnode_get_string(args->dnode, NULL);
305
306 offset = nb_running_get_entry(args->dnode, NULL, true);
307 if (offset->direct[direct].alist_name)
308 free(offset->direct[direct].alist_name);
309 offset->direct[direct].alist_name = strdup(alist_name);
310
311 return NB_OK;
312 }
313
314 /*
315 * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
316 */
317 int ripngd_instance_offset_list_metric_modify(struct nb_cb_modify_args *args)
318 {
319 int direct;
320 uint8_t metric;
321 struct ripng_offset_list *offset;
322
323 if (args->event != NB_EV_APPLY)
324 return NB_OK;
325
326 direct = yang_dnode_get_enum(args->dnode, "../direction");
327 metric = yang_dnode_get_uint8(args->dnode, NULL);
328
329 offset = nb_running_get_entry(args->dnode, NULL, true);
330 offset->direct[direct].metric = metric;
331
332 return NB_OK;
333 }
334
335 /*
336 * XPath: /frr-ripngd:ripngd/instance/passive-interface
337 */
338 int ripngd_instance_passive_interface_create(struct nb_cb_create_args *args)
339 {
340 struct ripng *ripng;
341 const char *ifname;
342
343 if (args->event != NB_EV_APPLY)
344 return NB_OK;
345
346 ripng = nb_running_get_entry(args->dnode, NULL, true);
347 ifname = yang_dnode_get_string(args->dnode, NULL);
348
349 return ripng_passive_interface_set(ripng, ifname);
350 }
351
352 int ripngd_instance_passive_interface_destroy(struct nb_cb_destroy_args *args)
353 {
354 struct ripng *ripng;
355 const char *ifname;
356
357 if (args->event != NB_EV_APPLY)
358 return NB_OK;
359
360 ripng = nb_running_get_entry(args->dnode, NULL, true);
361 ifname = yang_dnode_get_string(args->dnode, NULL);
362
363 return ripng_passive_interface_unset(ripng, ifname);
364 }
365
366 /*
367 * XPath: /frr-ripngd:ripngd/instance/redistribute
368 */
369 int ripngd_instance_redistribute_create(struct nb_cb_create_args *args)
370 {
371 struct ripng *ripng;
372 int type;
373
374 if (args->event != NB_EV_APPLY)
375 return NB_OK;
376
377 ripng = nb_running_get_entry(args->dnode, NULL, true);
378 type = yang_dnode_get_enum(args->dnode, "./protocol");
379
380 ripng->redist[type].enabled = true;
381
382 return NB_OK;
383 }
384
385 int ripngd_instance_redistribute_destroy(struct nb_cb_destroy_args *args)
386 {
387 struct ripng *ripng;
388 int type;
389
390 if (args->event != NB_EV_APPLY)
391 return NB_OK;
392
393 ripng = nb_running_get_entry(args->dnode, NULL, true);
394 type = yang_dnode_get_enum(args->dnode, "./protocol");
395
396 ripng->redist[type].enabled = false;
397 if (ripng->redist[type].route_map.name) {
398 free(ripng->redist[type].route_map.name);
399 ripng->redist[type].route_map.name = NULL;
400 ripng->redist[type].route_map.map = NULL;
401 }
402 ripng->redist[type].metric_config = false;
403 ripng->redist[type].metric = 0;
404
405 if (ripng->enabled)
406 ripng_redistribute_conf_delete(ripng, type);
407
408 return NB_OK;
409 }
410
411 void ripngd_instance_redistribute_apply_finish(
412 struct nb_cb_apply_finish_args *args)
413 {
414 struct ripng *ripng;
415 int type;
416
417 ripng = nb_running_get_entry(args->dnode, NULL, true);
418 type = yang_dnode_get_enum(args->dnode, "./protocol");
419
420 if (ripng->enabled)
421 ripng_redistribute_conf_update(ripng, type);
422 }
423
424 /*
425 * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
426 */
427 int ripngd_instance_redistribute_route_map_modify(
428 struct nb_cb_modify_args *args)
429 {
430 struct ripng *ripng;
431 int type;
432 const char *rmap_name;
433
434 if (args->event != NB_EV_APPLY)
435 return NB_OK;
436
437 ripng = nb_running_get_entry(args->dnode, NULL, true);
438 type = yang_dnode_get_enum(args->dnode, "../protocol");
439 rmap_name = yang_dnode_get_string(args->dnode, NULL);
440
441 if (ripng->redist[type].route_map.name)
442 free(ripng->redist[type].route_map.name);
443 ripng->redist[type].route_map.name = strdup(rmap_name);
444 ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
445
446 return NB_OK;
447 }
448
449 int ripngd_instance_redistribute_route_map_destroy(
450 struct nb_cb_destroy_args *args)
451 {
452 struct ripng *ripng;
453 int type;
454
455 if (args->event != NB_EV_APPLY)
456 return NB_OK;
457
458 ripng = nb_running_get_entry(args->dnode, NULL, true);
459 type = yang_dnode_get_enum(args->dnode, "../protocol");
460
461 free(ripng->redist[type].route_map.name);
462 ripng->redist[type].route_map.name = NULL;
463 ripng->redist[type].route_map.map = NULL;
464
465 return NB_OK;
466 }
467
468 /*
469 * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
470 */
471 int ripngd_instance_redistribute_metric_modify(struct nb_cb_modify_args *args)
472 {
473 struct ripng *ripng;
474 int type;
475 uint8_t metric;
476
477 if (args->event != NB_EV_APPLY)
478 return NB_OK;
479
480 ripng = nb_running_get_entry(args->dnode, NULL, true);
481 type = yang_dnode_get_enum(args->dnode, "../protocol");
482 metric = yang_dnode_get_uint8(args->dnode, NULL);
483
484 ripng->redist[type].metric_config = true;
485 ripng->redist[type].metric = metric;
486
487 return NB_OK;
488 }
489
490 int ripngd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args)
491 {
492 struct ripng *ripng;
493 int type;
494
495 if (args->event != NB_EV_APPLY)
496 return NB_OK;
497
498 ripng = nb_running_get_entry(args->dnode, NULL, true);
499 type = yang_dnode_get_enum(args->dnode, "../protocol");
500
501 ripng->redist[type].metric_config = false;
502 ripng->redist[type].metric = 0;
503
504 return NB_OK;
505 }
506
507 /*
508 * XPath: /frr-ripngd:ripngd/instance/if-route-maps/if-route-map
509 */
510 int ripngd_instance_if_route_maps_if_route_map_create(
511 struct nb_cb_create_args *args)
512 {
513 /* if_rmap is created when first routemap is added */
514 return NB_OK;
515 }
516
517 int ripngd_instance_if_route_maps_if_route_map_destroy(
518 struct nb_cb_destroy_args *args)
519 {
520 struct ripng *ripng;
521
522 if (args->event != NB_EV_APPLY)
523 return NB_OK;
524
525 /*
526 * YANG will prune edit deletes up to the most general deleted node so
527 * we need to handle deleting any existing state underneath and not
528 * count on those more specific callbacks being called individually.
529 */
530
531 ripng = nb_running_get_entry(args->dnode, NULL, true);
532 if_rmap_yang_destroy_cb(ripng->if_rmap_ctx, args->dnode);
533
534 return NB_OK;
535 }
536
537 static void if_route_map_modify(const struct lyd_node *dnode,
538 enum if_rmap_type type, bool delete)
539 {
540 struct ripng *ripng = nb_running_get_entry(dnode, NULL, true);
541
542 if_rmap_yang_modify_cb(ripng->if_rmap_ctx, dnode, type, delete);
543 }
544 /*
545 * XPath: /frr-ripng:ripng/instance/if-route-maps/if-route-map/in-route-map
546 */
547 int ripngd_instance_if_route_maps_if_route_map_in_route_map_modify(
548 struct nb_cb_modify_args *args)
549 {
550 if (args->event != NB_EV_APPLY)
551 return NB_OK;
552
553 if_route_map_modify(args->dnode, IF_RMAP_IN, false);
554
555 return NB_OK;
556 }
557
558 int ripngd_instance_if_route_maps_if_route_map_in_route_map_destroy(
559 struct nb_cb_destroy_args *args)
560 {
561 if (args->event != NB_EV_APPLY)
562 return NB_OK;
563
564 if_route_map_modify(args->dnode, IF_RMAP_IN, true);
565
566 return NB_OK;
567 }
568
569 /*
570 * XPath: /frr-ripngd:ripngd/instance/if-route-maps/if-route-map/out-route-map
571 */
572 int ripngd_instance_if_route_maps_if_route_map_out_route_map_modify(
573 struct nb_cb_modify_args *args)
574 {
575 if (args->event != NB_EV_APPLY)
576 return NB_OK;
577
578 if_route_map_modify(args->dnode, IF_RMAP_OUT, false);
579
580 return NB_OK;
581 }
582
583 int ripngd_instance_if_route_maps_if_route_map_out_route_map_destroy(
584 struct nb_cb_destroy_args *args)
585 {
586 if (args->event != NB_EV_APPLY)
587 return NB_OK;
588
589 if_route_map_modify(args->dnode, IF_RMAP_OUT, true);
590
591 return NB_OK;
592 }
593
594 /*
595 * XPath: /frr-ripngd:ripngd/instance/static-route
596 */
597 int ripngd_instance_static_route_create(struct nb_cb_create_args *args)
598 {
599 struct ripng *ripng;
600 struct prefix_ipv6 p;
601
602 if (args->event != NB_EV_APPLY)
603 return NB_OK;
604
605 ripng = nb_running_get_entry(args->dnode, NULL, true);
606 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
607 apply_mask_ipv6(&p);
608
609 ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
610 0, NULL, 0);
611
612 return NB_OK;
613 }
614
615 int ripngd_instance_static_route_destroy(struct nb_cb_destroy_args *args)
616 {
617 struct ripng *ripng;
618 struct prefix_ipv6 p;
619
620 if (args->event != NB_EV_APPLY)
621 return NB_OK;
622
623 ripng = nb_running_get_entry(args->dnode, NULL, true);
624 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
625 apply_mask_ipv6(&p);
626
627 ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
628 &p, 0);
629
630 return NB_OK;
631 }
632
633 /*
634 * XPath: /frr-ripngd:ripngd/instance/aggregate-address
635 */
636 int ripngd_instance_aggregate_address_create(struct nb_cb_create_args *args)
637 {
638 struct ripng *ripng;
639 struct prefix_ipv6 p;
640
641 if (args->event != NB_EV_APPLY)
642 return NB_OK;
643
644 ripng = nb_running_get_entry(args->dnode, NULL, true);
645 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
646 apply_mask_ipv6(&p);
647
648 ripng_aggregate_add(ripng, (struct prefix *)&p);
649
650 return NB_OK;
651 }
652
653 int ripngd_instance_aggregate_address_destroy(struct nb_cb_destroy_args *args)
654 {
655 struct ripng *ripng;
656 struct prefix_ipv6 p;
657
658 if (args->event != NB_EV_APPLY)
659 return NB_OK;
660
661 ripng = nb_running_get_entry(args->dnode, NULL, true);
662 yang_dnode_get_ipv6p(&p, args->dnode, NULL);
663 apply_mask_ipv6(&p);
664
665 ripng_aggregate_delete(ripng, (struct prefix *)&p);
666
667 return NB_OK;
668 }
669
670 /*
671 * XPath: /frr-ripngd:ripngd/instance/timers
672 */
673 void ripngd_instance_timers_apply_finish(struct nb_cb_apply_finish_args *args)
674 {
675 struct ripng *ripng;
676
677 ripng = nb_running_get_entry(args->dnode, NULL, true);
678
679 /* Reset update timer thread. */
680 ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
681 }
682
683 /*
684 * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
685 */
686 int ripngd_instance_timers_flush_interval_modify(struct nb_cb_modify_args *args)
687 {
688 struct ripng *ripng;
689
690 if (args->event != NB_EV_APPLY)
691 return NB_OK;
692
693 ripng = nb_running_get_entry(args->dnode, NULL, true);
694 ripng->garbage_time = yang_dnode_get_uint16(args->dnode, NULL);
695
696 return NB_OK;
697 }
698
699 /*
700 * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
701 */
702 int ripngd_instance_timers_holddown_interval_modify(
703 struct nb_cb_modify_args *args)
704 {
705 struct ripng *ripng;
706
707 if (args->event != NB_EV_APPLY)
708 return NB_OK;
709
710 ripng = nb_running_get_entry(args->dnode, NULL, true);
711 ripng->timeout_time = yang_dnode_get_uint16(args->dnode, NULL);
712
713 return NB_OK;
714 }
715
716 /*
717 * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
718 */
719 int ripngd_instance_timers_update_interval_modify(
720 struct nb_cb_modify_args *args)
721 {
722 struct ripng *ripng;
723
724 if (args->event != NB_EV_APPLY)
725 return NB_OK;
726
727 ripng = nb_running_get_entry(args->dnode, NULL, true);
728 ripng->update_time = yang_dnode_get_uint16(args->dnode, NULL);
729
730 return NB_OK;
731 }
732
733 /*
734 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
735 */
736 int lib_interface_ripng_split_horizon_modify(struct nb_cb_modify_args *args)
737 {
738 struct interface *ifp;
739 struct ripng_interface *ri;
740
741 if (args->event != NB_EV_APPLY)
742 return NB_OK;
743
744 ifp = nb_running_get_entry(args->dnode, NULL, true);
745 ri = ifp->info;
746 ri->split_horizon = yang_dnode_get_enum(args->dnode, NULL);
747
748 return NB_OK;
749 }