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