]> git.proxmox.com Git - mirror_frr.git/blob - bfdd/bfdd_nb_config.c
Merge pull request #7945 from volta-networks/feat_isis_snmp
[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-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_rx;
493
494 switch (args->event) {
495 case NB_EV_VALIDATE:
496 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
497 if (min_rx < 10000 || min_rx > 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_rx = yang_dnode_get_uint32(args->dnode, NULL);
507 bp = nb_running_get_entry(args->dnode, NULL, true);
508 if (bp->min_echo_rx == min_rx)
509 return NB_OK;
510
511 bp->min_echo_rx = min_rx;
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/sessions/single-hop
525 */
526 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args *args)
527 {
528 return bfd_session_create(args, false);
529 }
530
531 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args *args)
532 {
533 return bfd_session_destroy(args->event, args->dnode, false);
534 }
535
536 /*
537 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
538 */
539 int bfdd_bfd_sessions_single_hop_source_addr_modify(
540 struct nb_cb_modify_args *args)
541 {
542 return NB_OK;
543 }
544
545 int bfdd_bfd_sessions_single_hop_source_addr_destroy(
546 struct nb_cb_destroy_args *args)
547 {
548 return NB_OK;
549 }
550
551 /*
552 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/profile
553 */
554 int bfdd_bfd_sessions_single_hop_profile_modify(struct nb_cb_modify_args *args)
555 {
556 struct bfd_session *bs;
557
558 if (args->event != NB_EV_APPLY)
559 return NB_OK;
560
561 bs = nb_running_get_entry(args->dnode, NULL, true);
562 bfd_profile_apply(yang_dnode_get_string(args->dnode, NULL), bs);
563
564 return NB_OK;
565 }
566
567 int bfdd_bfd_sessions_single_hop_profile_destroy(
568 struct nb_cb_destroy_args *args)
569 {
570 struct bfd_session *bs;
571
572 if (args->event != NB_EV_APPLY)
573 return NB_OK;
574
575 bs = nb_running_get_entry(args->dnode, NULL, true);
576 bfd_profile_remove(bs);
577
578 return NB_OK;
579 }
580
581 /*
582 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
583 */
584 int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
585 struct nb_cb_modify_args *args)
586 {
587 uint8_t detection_multiplier = yang_dnode_get_uint8(args->dnode, NULL);
588 struct bfd_session *bs;
589
590 switch (args->event) {
591 case NB_EV_VALIDATE:
592 break;
593
594 case NB_EV_PREPARE:
595 /* NOTHING */
596 break;
597
598 case NB_EV_APPLY:
599 bs = nb_running_get_entry(args->dnode, NULL, true);
600 bs->peer_profile.detection_multiplier = detection_multiplier;
601 bfd_session_apply(bs);
602 break;
603
604 case NB_EV_ABORT:
605 /* NOTHING */
606 break;
607 }
608
609 return NB_OK;
610 }
611
612 /*
613 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
614 */
615 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
616 struct nb_cb_modify_args *args)
617 {
618 uint32_t tx_interval = yang_dnode_get_uint32(args->dnode, NULL);
619 struct bfd_session *bs;
620
621 switch (args->event) {
622 case NB_EV_VALIDATE:
623 if (tx_interval < 10000 || tx_interval > 60000000)
624 return NB_ERR_VALIDATION;
625 break;
626
627 case NB_EV_PREPARE:
628 /* NOTHING */
629 break;
630
631 case NB_EV_APPLY:
632 bs = nb_running_get_entry(args->dnode, NULL, true);
633 if (tx_interval == bs->timers.desired_min_tx)
634 return NB_OK;
635
636 bs->peer_profile.min_tx = tx_interval;
637 bfd_session_apply(bs);
638 break;
639
640 case NB_EV_ABORT:
641 /* NOTHING */
642 break;
643 }
644
645 return NB_OK;
646 }
647
648 /*
649 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
650 */
651 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
652 struct nb_cb_modify_args *args)
653 {
654 uint32_t rx_interval = yang_dnode_get_uint32(args->dnode, NULL);
655 struct bfd_session *bs;
656
657 switch (args->event) {
658 case NB_EV_VALIDATE:
659 if (rx_interval < 10000 || rx_interval > 60000000)
660 return NB_ERR_VALIDATION;
661 break;
662
663 case NB_EV_PREPARE:
664 /* NOTHING */
665 break;
666
667 case NB_EV_APPLY:
668 bs = nb_running_get_entry(args->dnode, NULL, true);
669 if (rx_interval == bs->timers.required_min_rx)
670 return NB_OK;
671
672 bs->peer_profile.min_rx = rx_interval;
673 bfd_session_apply(bs);
674 break;
675
676 case NB_EV_ABORT:
677 /* NOTHING */
678 break;
679 }
680
681 return NB_OK;
682 }
683
684 /*
685 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
686 */
687 int bfdd_bfd_sessions_single_hop_administrative_down_modify(
688 struct nb_cb_modify_args *args)
689 {
690 bool shutdown = yang_dnode_get_bool(args->dnode, NULL);
691 struct bfd_session *bs;
692
693 switch (args->event) {
694 case NB_EV_VALIDATE:
695 case NB_EV_PREPARE:
696 return NB_OK;
697
698 case NB_EV_APPLY:
699 break;
700
701 case NB_EV_ABORT:
702 return NB_OK;
703 }
704
705 bs = nb_running_get_entry(args->dnode, NULL, true);
706 bs->peer_profile.admin_shutdown = shutdown;
707 bfd_session_apply(bs);
708
709 return NB_OK;
710 }
711
712 /*
713 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode
714 */
715 int bfdd_bfd_sessions_single_hop_passive_mode_modify(
716 struct nb_cb_modify_args *args)
717 {
718 struct bfd_session *bs;
719 bool passive;
720
721 switch (args->event) {
722 case NB_EV_VALIDATE:
723 case NB_EV_PREPARE:
724 return NB_OK;
725
726 case NB_EV_APPLY:
727 break;
728
729 case NB_EV_ABORT:
730 return NB_OK;
731 }
732
733 passive = yang_dnode_get_bool(args->dnode, NULL);
734
735 bs = nb_running_get_entry(args->dnode, NULL, true);
736 bs->peer_profile.passive = passive;
737 bfd_session_apply(bs);
738
739 return NB_OK;
740 }
741
742 /*
743 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
744 */
745 int bfdd_bfd_sessions_single_hop_echo_mode_modify(
746 struct nb_cb_modify_args *args)
747 {
748 bool echo = yang_dnode_get_bool(args->dnode, NULL);
749 struct bfd_session *bs;
750
751 switch (args->event) {
752 case NB_EV_VALIDATE:
753 case NB_EV_PREPARE:
754 return NB_OK;
755
756 case NB_EV_APPLY:
757 break;
758
759 case NB_EV_ABORT:
760 return NB_OK;
761 }
762
763 bs = nb_running_get_entry(args->dnode, NULL, true);
764 bs->peer_profile.echo_mode = echo;
765 bfd_session_apply(bs);
766
767 return NB_OK;
768 }
769
770 /*
771 * XPath:
772 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
773 */
774 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
775 struct nb_cb_modify_args *args)
776 {
777 uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
778 struct bfd_session *bs;
779
780 switch (args->event) {
781 case NB_EV_VALIDATE:
782 if (echo_interval < 10000 || echo_interval > 60000000)
783 return NB_ERR_VALIDATION;
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 if (echo_interval == bs->timers.required_min_echo)
793 return NB_OK;
794
795 bs->peer_profile.min_echo_rx = echo_interval;
796 bfd_session_apply(bs);
797 break;
798
799 case NB_EV_ABORT:
800 /* NOTHING */
801 break;
802 }
803
804 return NB_OK;
805 }
806
807 /*
808 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
809 */
810 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args *args)
811 {
812 return bfd_session_create(args, true);
813 }
814
815 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args *args)
816 {
817 return bfd_session_destroy(args->event, args->dnode, true);
818 }
819
820 /*
821 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl
822 */
823 int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
824 struct nb_cb_modify_args *args)
825 {
826 struct bfd_session *bs;
827
828 switch (args->event) {
829 case NB_EV_VALIDATE:
830 case NB_EV_PREPARE:
831 return NB_OK;
832
833 case NB_EV_APPLY:
834 break;
835
836 case NB_EV_ABORT:
837 return NB_OK;
838 }
839
840 bs = nb_running_get_entry(args->dnode, NULL, true);
841 bs->peer_profile.minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
842 bfd_session_apply(bs);
843
844 return NB_OK;
845 }
846
847 int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
848 struct nb_cb_destroy_args *args)
849 {
850 struct bfd_session *bs;
851
852 switch (args->event) {
853 case NB_EV_VALIDATE:
854 case NB_EV_PREPARE:
855 return NB_OK;
856
857 case NB_EV_APPLY:
858 break;
859
860 case NB_EV_ABORT:
861 return NB_OK;
862 }
863
864 bs = nb_running_get_entry(args->dnode, NULL, true);
865 bs->peer_profile.minimum_ttl = BFD_DEF_MHOP_TTL;
866 bfd_session_apply(bs);
867
868 return NB_OK;
869 }