]> git.proxmox.com Git - mirror_frr.git/blob - bfdd/bfdd_nb_config.c
Merge pull request #8129 from mjstapp/backup_recursives
[mirror_frr.git] / bfdd / bfdd_nb_config.c
1 /*
2 * BFD daemon northbound implementation.
3 *
4 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
5 * Rafael Zalamena
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA.
21 */
22
23 #include <zebra.h>
24
25 #include "lib/log.h"
26 #include "lib/northbound.h"
27
28 #include "bfd.h"
29 #include "bfdd_nb.h"
30
31 /*
32 * Helpers.
33 */
34 static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
35 struct bfd_key *bk)
36 {
37 const char *ifname = NULL, *vrfname = NULL;
38 struct sockaddr_any psa, lsa;
39
40 /* Required destination parameter. */
41 strtosa(yang_dnode_get_string(dnode, "./dest-addr"), &psa);
42
43 /* Get optional source address. */
44 memset(&lsa, 0, sizeof(lsa));
45 if (yang_dnode_exists(dnode, "./source-addr"))
46 strtosa(yang_dnode_get_string(dnode, "./source-addr"), &lsa);
47
48 ifname = yang_dnode_get_string(dnode, "./interface");
49 vrfname = yang_dnode_get_string(dnode, "./vrf");
50
51 if (strcmp(ifname, "*") == 0)
52 ifname = NULL;
53
54 /* Generate the corresponding key. */
55 gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname);
56 }
57
58 struct session_iter {
59 int count;
60 bool wildcard;
61 };
62
63 static int session_iter_cb(const struct lyd_node *dnode, void *arg)
64 {
65 struct session_iter *iter = arg;
66 const char *ifname;
67
68 ifname = yang_dnode_get_string(dnode, "./interface");
69
70 if (strmatch(ifname, "*"))
71 iter->wildcard = true;
72
73 iter->count++;
74
75 return YANG_ITER_CONTINUE;
76 }
77
78 static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)
79 {
80 const struct lyd_node *sess_dnode;
81 struct session_iter iter;
82 struct bfd_session *bs;
83 const char *source;
84 const char *dest;
85 const char *ifname;
86 const char *vrfname;
87 struct bfd_key bk;
88 struct prefix p;
89
90 switch (args->event) {
91 case NB_EV_VALIDATE:
92 /*
93 * When `dest-addr` is IPv6 and link-local we must
94 * require interface name, otherwise we can't figure
95 * which interface to use to send the packets.
96 */
97 yang_dnode_get_prefix(&p, args->dnode, "./dest-addr");
98
99 ifname = yang_dnode_get_string(args->dnode, "./interface");
100
101 if (p.family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)
102 && strcmp(ifname, "*") == 0) {
103 snprintf(
104 args->errmsg, args->errmsg_len,
105 "When using link-local you must specify an interface");
106 return NB_ERR_VALIDATION;
107 }
108
109 iter.count = 0;
110 iter.wildcard = false;
111
112 sess_dnode = yang_dnode_get_parent(args->dnode, "sessions");
113
114 dest = yang_dnode_get_string(args->dnode, "./dest-addr");
115 vrfname = yang_dnode_get_string(args->dnode, "./vrf");
116
117 if (mhop) {
118 source = yang_dnode_get_string(args->dnode, "./source-addr");
119
120 yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
121 "./multi-hop[source-addr='%s'][dest-addr='%s'][vrf='%s']",
122 source, dest, vrfname);
123 } else {
124 yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
125 "./single-hop[dest-addr='%s'][vrf='%s']",
126 dest, vrfname);
127 }
128
129 if (iter.wildcard && iter.count > 1) {
130 snprintf(
131 args->errmsg, args->errmsg_len,
132 "It is not allowed to configure the same peer with and without ifname");
133 return NB_ERR_VALIDATION;
134 }
135 break;
136
137 case NB_EV_PREPARE:
138 bfd_session_get_key(mhop, args->dnode, &bk);
139 bs = bfd_key_lookup(bk);
140
141 /* This session was already configured by another daemon. */
142 if (bs != NULL) {
143 /* Now it is configured also by CLI. */
144 SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
145 bs->refcount++;
146
147 args->resource->ptr = bs;
148 break;
149 }
150
151 bs = bfd_session_new();
152
153 /* Fill the session key. */
154 bfd_session_get_key(mhop, args->dnode, &bs->key);
155
156 /* Set configuration flags. */
157 bs->refcount = 1;
158 SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
159 if (mhop)
160 SET_FLAG(bs->flags, BFD_SESS_FLAG_MH);
161 if (bs->key.family == AF_INET6)
162 SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
163
164 args->resource->ptr = bs;
165 break;
166
167 case NB_EV_APPLY:
168 bs = args->resource->ptr;
169
170 /* Only attempt to registrate if freshly allocated. */
171 if (bs->discrs.my_discr == 0 && bs_registrate(bs) == NULL)
172 return NB_ERR_RESOURCE;
173
174 nb_running_set_entry(args->dnode, bs);
175 break;
176
177 case NB_EV_ABORT:
178 bs = args->resource->ptr;
179 if (bs->refcount <= 1)
180 bfd_session_free(bs);
181 break;
182 }
183
184 return NB_OK;
185 }
186
187 static int bfd_session_destroy(enum nb_event event,
188 const struct lyd_node *dnode, bool mhop)
189 {
190 struct bfd_session *bs;
191 struct bfd_key bk;
192
193 switch (event) {
194 case NB_EV_VALIDATE:
195 bfd_session_get_key(mhop, dnode, &bk);
196 if (bfd_key_lookup(bk) == NULL)
197 return NB_ERR_INCONSISTENCY;
198 break;
199
200 case NB_EV_PREPARE:
201 /* NOTHING */
202 break;
203
204 case NB_EV_APPLY:
205 bs = nb_running_unset_entry(dnode);
206 /* CLI is not using this session anymore. */
207 if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) == 0)
208 break;
209
210 UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
211 bs->refcount--;
212 /* There are still daemons using it. */
213 if (bs->refcount > 0)
214 break;
215
216 bfd_session_free(bs);
217 break;
218
219 case NB_EV_ABORT:
220 /* NOTHING */
221 break;
222 }
223
224 return NB_OK;
225 }
226
227 /*
228 * XPath: /frr-bfdd:bfdd/bfd
229 */
230 int bfdd_bfd_create(struct nb_cb_create_args *args)
231 {
232 /* NOTHING */
233 return NB_OK;
234 }
235
236 int bfdd_bfd_destroy(struct nb_cb_destroy_args *args)
237 {
238 switch (args->event) {
239 case NB_EV_VALIDATE:
240 /* NOTHING */
241 return NB_OK;
242
243 case NB_EV_PREPARE:
244 /* NOTHING */
245 return NB_OK;
246
247 case NB_EV_APPLY:
248 bfd_sessions_remove_manual();
249 break;
250
251 case NB_EV_ABORT:
252 /* NOTHING */
253 return NB_OK;
254 }
255
256 return NB_OK;
257 }
258
259 /*
260 * XPath: /frr-bfdd:bfdd/bfd/profile
261 */
262 int bfdd_bfd_profile_create(struct nb_cb_create_args *args)
263 {
264 struct bfd_profile *bp;
265 const char *name;
266
267 if (args->event != NB_EV_APPLY)
268 return NB_OK;
269
270 name = yang_dnode_get_string(args->dnode, "./name");
271 bp = bfd_profile_new(name);
272 nb_running_set_entry(args->dnode, bp);
273
274 return NB_OK;
275 }
276
277 int bfdd_bfd_profile_destroy(struct nb_cb_destroy_args *args)
278 {
279 struct bfd_profile *bp;
280
281 if (args->event != NB_EV_APPLY)
282 return NB_OK;
283
284 bp = nb_running_unset_entry(args->dnode);
285 bfd_profile_free(bp);
286
287 return NB_OK;
288 }
289
290 /*
291 * XPath: /frr-bfdd:bfdd/bfd/profile/detection-multiplier
292 */
293 int bfdd_bfd_profile_detection_multiplier_modify(struct nb_cb_modify_args *args)
294 {
295 struct bfd_profile *bp;
296
297 if (args->event != NB_EV_APPLY)
298 return NB_OK;
299
300 bp = nb_running_get_entry(args->dnode, NULL, true);
301 bp->detection_multiplier = yang_dnode_get_uint8(args->dnode, NULL);
302 bfd_profile_update(bp);
303
304 return NB_OK;
305 }
306
307 /*
308 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-transmission-interval
309 */
310 int bfdd_bfd_profile_desired_transmission_interval_modify(
311 struct nb_cb_modify_args *args)
312 {
313 struct bfd_profile *bp;
314 uint32_t min_tx;
315
316 switch (args->event) {
317 case NB_EV_VALIDATE:
318 min_tx = yang_dnode_get_uint32(args->dnode, NULL);
319 if (min_tx < 10000 || min_tx > 60000000)
320 return NB_ERR_VALIDATION;
321 break;
322
323 case NB_EV_PREPARE:
324 /* NOTHING */
325 break;
326
327 case NB_EV_APPLY:
328 min_tx = yang_dnode_get_uint32(args->dnode, NULL);
329 bp = nb_running_get_entry(args->dnode, NULL, true);
330 if (bp->min_tx == min_tx)
331 return NB_OK;
332
333 bp->min_tx = min_tx;
334 bfd_profile_update(bp);
335 break;
336
337 case NB_EV_ABORT:
338 /* NOTHING */
339 break;
340 }
341
342 return NB_OK;
343 }
344
345 /*
346 * XPath: /frr-bfdd:bfdd/bfd/profile/required-receive-interval
347 */
348 int bfdd_bfd_profile_required_receive_interval_modify(
349 struct nb_cb_modify_args *args)
350 {
351 struct bfd_profile *bp;
352 uint32_t min_rx;
353
354 switch (args->event) {
355 case NB_EV_VALIDATE:
356 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
357 if (min_rx < 10000 || min_rx > 60000000)
358 return NB_ERR_VALIDATION;
359 break;
360
361 case NB_EV_PREPARE:
362 /* NOTHING */
363 break;
364
365 case NB_EV_APPLY:
366 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
367 bp = nb_running_get_entry(args->dnode, NULL, true);
368 if (bp->min_rx == min_rx)
369 return NB_OK;
370
371 bp->min_rx = min_rx;
372 bfd_profile_update(bp);
373 break;
374
375 case NB_EV_ABORT:
376 /* NOTHING */
377 break;
378 }
379
380 return NB_OK;
381 }
382
383 /*
384 * XPath: /frr-bfdd:bfdd/bfd/profile/administrative-down
385 */
386 int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
387 {
388 struct bfd_profile *bp;
389 bool shutdown;
390
391 if (args->event != NB_EV_APPLY)
392 return NB_OK;
393
394 shutdown = yang_dnode_get_bool(args->dnode, NULL);
395 bp = nb_running_get_entry(args->dnode, NULL, true);
396 if (bp->admin_shutdown == shutdown)
397 return NB_OK;
398
399 bp->admin_shutdown = shutdown;
400 bfd_profile_update(bp);
401
402 return NB_OK;
403 }
404
405 /*
406 * XPath: /frr-bfdd:bfdd/bfd/profile/passive-mode
407 */
408 int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
409 {
410 struct bfd_profile *bp;
411 bool passive;
412
413 if (args->event != NB_EV_APPLY)
414 return NB_OK;
415
416 passive = yang_dnode_get_bool(args->dnode, NULL);
417 bp = nb_running_get_entry(args->dnode, NULL, true);
418 if (bp->passive == passive)
419 return NB_OK;
420
421 bp->passive = passive;
422 bfd_profile_update(bp);
423
424 return NB_OK;
425 }
426
427 /*
428 * XPath: /frr-bfdd:bfdd/bfd/profile/minimum-ttl
429 */
430 int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args *args)
431 {
432 struct bfd_profile *bp;
433 uint8_t minimum_ttl;
434
435 if (args->event != NB_EV_APPLY)
436 return NB_OK;
437
438 minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
439 bp = nb_running_get_entry(args->dnode, NULL, true);
440 if (bp->minimum_ttl == minimum_ttl)
441 return NB_OK;
442
443 bp->minimum_ttl = minimum_ttl;
444 bfd_profile_update(bp);
445
446 return NB_OK;
447 }
448
449 int bfdd_bfd_profile_minimum_ttl_destroy(struct nb_cb_destroy_args *args)
450 {
451 struct bfd_profile *bp;
452
453 if (args->event != NB_EV_APPLY)
454 return NB_OK;
455
456 bp = nb_running_get_entry(args->dnode, NULL, true);
457 bp->minimum_ttl = BFD_DEF_MHOP_TTL;
458 bfd_profile_update(bp);
459
460 return NB_OK;
461 }
462
463 /*
464 * XPath: /frr-bfdd:bfdd/bfd/profile/echo-mode
465 */
466 int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args *args)
467 {
468 struct bfd_profile *bp;
469 bool echo;
470
471 if (args->event != NB_EV_APPLY)
472 return NB_OK;
473
474 echo = yang_dnode_get_bool(args->dnode, NULL);
475 bp = nb_running_get_entry(args->dnode, NULL, true);
476 if (bp->echo_mode == echo)
477 return NB_OK;
478
479 bp->echo_mode = echo;
480 bfd_profile_update(bp);
481
482 return NB_OK;
483 }
484
485 /*
486 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-echo-transmission-interval
487 */
488 int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
489 struct nb_cb_modify_args *args)
490 {
491 struct bfd_profile *bp;
492 uint32_t min_tx;
493
494 switch (args->event) {
495 case NB_EV_VALIDATE:
496 min_tx = yang_dnode_get_uint32(args->dnode, NULL);
497 if (min_tx < 10000 || min_tx > 60000000)
498 return NB_ERR_VALIDATION;
499 break;
500
501 case NB_EV_PREPARE:
502 /* NOTHING */
503 break;
504
505 case NB_EV_APPLY:
506 min_tx = yang_dnode_get_uint32(args->dnode, NULL);
507 bp = nb_running_get_entry(args->dnode, NULL, true);
508 if (bp->min_echo_tx == min_tx)
509 return NB_OK;
510
511 bp->min_echo_tx = min_tx;
512 bfd_profile_update(bp);
513 break;
514
515 case NB_EV_ABORT:
516 /* NOTHING */
517 break;
518 }
519
520 return NB_OK;
521 }
522
523 /*
524 * XPath: /frr-bfdd:bfdd/bfd/profile/required-echo-receive-interval
525 */
526 int bfdd_bfd_profile_required_echo_receive_interval_modify(
527 struct nb_cb_modify_args *args)
528 {
529 struct bfd_profile *bp;
530 uint32_t min_rx;
531
532 switch (args->event) {
533 case NB_EV_VALIDATE:
534 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
535 if (min_rx == 0)
536 return NB_OK;
537 if (min_rx < 10000 || min_rx > 60000000)
538 return NB_ERR_VALIDATION;
539 break;
540
541 case NB_EV_PREPARE:
542 /* NOTHING */
543 break;
544
545 case NB_EV_APPLY:
546 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
547 bp = nb_running_get_entry(args->dnode, NULL, true);
548 if (bp->min_echo_rx == min_rx)
549 return NB_OK;
550
551 bp->min_echo_rx = min_rx;
552 bfd_profile_update(bp);
553 break;
554
555 case NB_EV_ABORT:
556 /* NOTHING */
557 break;
558 }
559
560 return NB_OK;
561 }
562
563 /*
564 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop
565 */
566 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args *args)
567 {
568 return bfd_session_create(args, false);
569 }
570
571 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args *args)
572 {
573 return bfd_session_destroy(args->event, args->dnode, false);
574 }
575
576 /*
577 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
578 */
579 int bfdd_bfd_sessions_single_hop_source_addr_modify(
580 struct nb_cb_modify_args *args)
581 {
582 return NB_OK;
583 }
584
585 int bfdd_bfd_sessions_single_hop_source_addr_destroy(
586 struct nb_cb_destroy_args *args)
587 {
588 return NB_OK;
589 }
590
591 /*
592 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/profile
593 */
594 int bfdd_bfd_sessions_single_hop_profile_modify(struct nb_cb_modify_args *args)
595 {
596 struct bfd_session *bs;
597
598 if (args->event != NB_EV_APPLY)
599 return NB_OK;
600
601 bs = nb_running_get_entry(args->dnode, NULL, true);
602 bfd_profile_apply(yang_dnode_get_string(args->dnode, NULL), bs);
603
604 return NB_OK;
605 }
606
607 int bfdd_bfd_sessions_single_hop_profile_destroy(
608 struct nb_cb_destroy_args *args)
609 {
610 struct bfd_session *bs;
611
612 if (args->event != NB_EV_APPLY)
613 return NB_OK;
614
615 bs = nb_running_get_entry(args->dnode, NULL, true);
616 bfd_profile_remove(bs);
617
618 return NB_OK;
619 }
620
621 /*
622 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
623 */
624 int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
625 struct nb_cb_modify_args *args)
626 {
627 uint8_t detection_multiplier = yang_dnode_get_uint8(args->dnode, NULL);
628 struct bfd_session *bs;
629
630 switch (args->event) {
631 case NB_EV_VALIDATE:
632 break;
633
634 case NB_EV_PREPARE:
635 /* NOTHING */
636 break;
637
638 case NB_EV_APPLY:
639 bs = nb_running_get_entry(args->dnode, NULL, true);
640 bs->peer_profile.detection_multiplier = detection_multiplier;
641 bfd_session_apply(bs);
642 break;
643
644 case NB_EV_ABORT:
645 /* NOTHING */
646 break;
647 }
648
649 return NB_OK;
650 }
651
652 /*
653 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
654 */
655 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
656 struct nb_cb_modify_args *args)
657 {
658 uint32_t tx_interval = yang_dnode_get_uint32(args->dnode, NULL);
659 struct bfd_session *bs;
660
661 switch (args->event) {
662 case NB_EV_VALIDATE:
663 if (tx_interval < 10000 || tx_interval > 60000000)
664 return NB_ERR_VALIDATION;
665 break;
666
667 case NB_EV_PREPARE:
668 /* NOTHING */
669 break;
670
671 case NB_EV_APPLY:
672 bs = nb_running_get_entry(args->dnode, NULL, true);
673 if (tx_interval == bs->timers.desired_min_tx)
674 return NB_OK;
675
676 bs->peer_profile.min_tx = tx_interval;
677 bfd_session_apply(bs);
678 break;
679
680 case NB_EV_ABORT:
681 /* NOTHING */
682 break;
683 }
684
685 return NB_OK;
686 }
687
688 /*
689 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
690 */
691 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
692 struct nb_cb_modify_args *args)
693 {
694 uint32_t rx_interval = yang_dnode_get_uint32(args->dnode, NULL);
695 struct bfd_session *bs;
696
697 switch (args->event) {
698 case NB_EV_VALIDATE:
699 if (rx_interval < 10000 || rx_interval > 60000000)
700 return NB_ERR_VALIDATION;
701 break;
702
703 case NB_EV_PREPARE:
704 /* NOTHING */
705 break;
706
707 case NB_EV_APPLY:
708 bs = nb_running_get_entry(args->dnode, NULL, true);
709 if (rx_interval == bs->timers.required_min_rx)
710 return NB_OK;
711
712 bs->peer_profile.min_rx = rx_interval;
713 bfd_session_apply(bs);
714 break;
715
716 case NB_EV_ABORT:
717 /* NOTHING */
718 break;
719 }
720
721 return NB_OK;
722 }
723
724 /*
725 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
726 */
727 int bfdd_bfd_sessions_single_hop_administrative_down_modify(
728 struct nb_cb_modify_args *args)
729 {
730 bool shutdown = yang_dnode_get_bool(args->dnode, NULL);
731 struct bfd_session *bs;
732
733 switch (args->event) {
734 case NB_EV_VALIDATE:
735 case NB_EV_PREPARE:
736 return NB_OK;
737
738 case NB_EV_APPLY:
739 break;
740
741 case NB_EV_ABORT:
742 return NB_OK;
743 }
744
745 bs = nb_running_get_entry(args->dnode, NULL, true);
746 bs->peer_profile.admin_shutdown = shutdown;
747 bfd_session_apply(bs);
748
749 return NB_OK;
750 }
751
752 /*
753 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode
754 */
755 int bfdd_bfd_sessions_single_hop_passive_mode_modify(
756 struct nb_cb_modify_args *args)
757 {
758 struct bfd_session *bs;
759 bool passive;
760
761 switch (args->event) {
762 case NB_EV_VALIDATE:
763 case NB_EV_PREPARE:
764 return NB_OK;
765
766 case NB_EV_APPLY:
767 break;
768
769 case NB_EV_ABORT:
770 return NB_OK;
771 }
772
773 passive = yang_dnode_get_bool(args->dnode, NULL);
774
775 bs = nb_running_get_entry(args->dnode, NULL, true);
776 bs->peer_profile.passive = passive;
777 bfd_session_apply(bs);
778
779 return NB_OK;
780 }
781
782 /*
783 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
784 */
785 int bfdd_bfd_sessions_single_hop_echo_mode_modify(
786 struct nb_cb_modify_args *args)
787 {
788 bool echo = yang_dnode_get_bool(args->dnode, NULL);
789 struct bfd_session *bs;
790
791 switch (args->event) {
792 case NB_EV_VALIDATE:
793 case NB_EV_PREPARE:
794 return NB_OK;
795
796 case NB_EV_APPLY:
797 break;
798
799 case NB_EV_ABORT:
800 return NB_OK;
801 }
802
803 bs = nb_running_get_entry(args->dnode, NULL, true);
804 bs->peer_profile.echo_mode = echo;
805 bfd_session_apply(bs);
806
807 return NB_OK;
808 }
809
810 /*
811 * XPath:
812 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
813 */
814 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
815 struct nb_cb_modify_args *args)
816 {
817 uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
818 struct bfd_session *bs;
819
820 switch (args->event) {
821 case NB_EV_VALIDATE:
822 if (echo_interval < 10000 || echo_interval > 60000000)
823 return NB_ERR_VALIDATION;
824 break;
825
826 case NB_EV_PREPARE:
827 /* NOTHING */
828 break;
829
830 case NB_EV_APPLY:
831 bs = nb_running_get_entry(args->dnode, NULL, true);
832 if (echo_interval == bs->timers.desired_min_echo_tx)
833 return NB_OK;
834
835 bs->peer_profile.min_echo_tx = echo_interval;
836 bfd_session_apply(bs);
837 break;
838
839 case NB_EV_ABORT:
840 /* NOTHING */
841 break;
842 }
843
844 return NB_OK;
845 }
846
847 /*
848 * XPath:
849 * /frr-bfdd:bfdd/bfd/sessions/single-hop/required-echo-receive-interval
850 */
851 int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
852 struct nb_cb_modify_args *args)
853 {
854 uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
855 struct bfd_session *bs;
856
857 switch (args->event) {
858 case NB_EV_VALIDATE:
859 if (echo_interval == 0)
860 return NB_OK;
861 if (echo_interval < 10000 || echo_interval > 60000000)
862 return NB_ERR_VALIDATION;
863 break;
864
865 case NB_EV_PREPARE:
866 /* NOTHING */
867 break;
868
869 case NB_EV_APPLY:
870 bs = nb_running_get_entry(args->dnode, NULL, true);
871 if (echo_interval == bs->timers.required_min_echo_rx)
872 return NB_OK;
873
874 bs->peer_profile.min_echo_rx = echo_interval;
875 bfd_session_apply(bs);
876 break;
877
878 case NB_EV_ABORT:
879 /* NOTHING */
880 break;
881 }
882
883 return NB_OK;
884 }
885
886 /*
887 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
888 */
889 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args *args)
890 {
891 return bfd_session_create(args, true);
892 }
893
894 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args *args)
895 {
896 return bfd_session_destroy(args->event, args->dnode, true);
897 }
898
899 /*
900 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl
901 */
902 int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
903 struct nb_cb_modify_args *args)
904 {
905 struct bfd_session *bs;
906
907 switch (args->event) {
908 case NB_EV_VALIDATE:
909 case NB_EV_PREPARE:
910 return NB_OK;
911
912 case NB_EV_APPLY:
913 break;
914
915 case NB_EV_ABORT:
916 return NB_OK;
917 }
918
919 bs = nb_running_get_entry(args->dnode, NULL, true);
920 bs->peer_profile.minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
921 bfd_session_apply(bs);
922
923 return NB_OK;
924 }
925
926 int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
927 struct nb_cb_destroy_args *args)
928 {
929 struct bfd_session *bs;
930
931 switch (args->event) {
932 case NB_EV_VALIDATE:
933 case NB_EV_PREPARE:
934 return NB_OK;
935
936 case NB_EV_APPLY:
937 break;
938
939 case NB_EV_ABORT:
940 return NB_OK;
941 }
942
943 bs = nb_running_get_entry(args->dnode, NULL, true);
944 bs->peer_profile.minimum_ttl = BFD_DEF_MHOP_TTL;
945 bfd_session_apply(bs);
946
947 return NB_OK;
948 }