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