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