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