]> git.proxmox.com Git - mirror_frr.git/blob - bfdd/bfdd_nb_config.c
Merge pull request #8691 from louis-oui/split-soft-reconfig
[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 uint32_t min_tx;
337
338 switch (args->event) {
339 case NB_EV_VALIDATE:
340 min_tx = yang_dnode_get_uint32(args->dnode, NULL);
341 if (min_tx < 10000 || min_tx > 60000000)
342 return NB_ERR_VALIDATION;
343 break;
344
345 case NB_EV_PREPARE:
346 /* NOTHING */
347 break;
348
349 case NB_EV_APPLY:
350 min_tx = yang_dnode_get_uint32(args->dnode, NULL);
351 bp = nb_running_get_entry(args->dnode, NULL, true);
352 if (bp->min_tx == min_tx)
353 return NB_OK;
354
355 bp->min_tx = min_tx;
356 bfd_profile_update(bp);
357 break;
358
359 case NB_EV_ABORT:
360 /* NOTHING */
361 break;
362 }
363
364 return NB_OK;
365 }
366
367 /*
368 * XPath: /frr-bfdd:bfdd/bfd/profile/required-receive-interval
369 */
370 int bfdd_bfd_profile_required_receive_interval_modify(
371 struct nb_cb_modify_args *args)
372 {
373 struct bfd_profile *bp;
374 uint32_t min_rx;
375
376 switch (args->event) {
377 case NB_EV_VALIDATE:
378 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
379 if (min_rx < 10000 || min_rx > 60000000)
380 return NB_ERR_VALIDATION;
381 break;
382
383 case NB_EV_PREPARE:
384 /* NOTHING */
385 break;
386
387 case NB_EV_APPLY:
388 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
389 bp = nb_running_get_entry(args->dnode, NULL, true);
390 if (bp->min_rx == min_rx)
391 return NB_OK;
392
393 bp->min_rx = min_rx;
394 bfd_profile_update(bp);
395 break;
396
397 case NB_EV_ABORT:
398 /* NOTHING */
399 break;
400 }
401
402 return NB_OK;
403 }
404
405 /*
406 * XPath: /frr-bfdd:bfdd/bfd/profile/administrative-down
407 */
408 int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
409 {
410 struct bfd_profile *bp;
411 bool shutdown;
412
413 if (args->event != NB_EV_APPLY)
414 return NB_OK;
415
416 shutdown = yang_dnode_get_bool(args->dnode, NULL);
417 bp = nb_running_get_entry(args->dnode, NULL, true);
418 if (bp->admin_shutdown == shutdown)
419 return NB_OK;
420
421 bp->admin_shutdown = shutdown;
422 bfd_profile_update(bp);
423
424 return NB_OK;
425 }
426
427 /*
428 * XPath: /frr-bfdd:bfdd/bfd/profile/passive-mode
429 */
430 int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
431 {
432 struct bfd_profile *bp;
433 bool passive;
434
435 if (args->event != NB_EV_APPLY)
436 return NB_OK;
437
438 passive = yang_dnode_get_bool(args->dnode, NULL);
439 bp = nb_running_get_entry(args->dnode, NULL, true);
440 if (bp->passive == passive)
441 return NB_OK;
442
443 bp->passive = passive;
444 bfd_profile_update(bp);
445
446 return NB_OK;
447 }
448
449 /*
450 * XPath: /frr-bfdd:bfdd/bfd/profile/minimum-ttl
451 */
452 int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args *args)
453 {
454 struct bfd_profile *bp;
455 uint8_t minimum_ttl;
456
457 if (args->event != NB_EV_APPLY)
458 return NB_OK;
459
460 minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
461 bp = nb_running_get_entry(args->dnode, NULL, true);
462 if (bp->minimum_ttl == minimum_ttl)
463 return NB_OK;
464
465 bp->minimum_ttl = minimum_ttl;
466 bfd_profile_update(bp);
467
468 return NB_OK;
469 }
470
471 int bfdd_bfd_profile_minimum_ttl_destroy(struct nb_cb_destroy_args *args)
472 {
473 struct bfd_profile *bp;
474
475 if (args->event != NB_EV_APPLY)
476 return NB_OK;
477
478 bp = nb_running_get_entry(args->dnode, NULL, true);
479 bp->minimum_ttl = BFD_DEF_MHOP_TTL;
480 bfd_profile_update(bp);
481
482 return NB_OK;
483 }
484
485 /*
486 * XPath: /frr-bfdd:bfdd/bfd/profile/echo-mode
487 */
488 int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args *args)
489 {
490 struct bfd_profile *bp;
491 bool echo;
492
493 if (args->event != NB_EV_APPLY)
494 return NB_OK;
495
496 echo = yang_dnode_get_bool(args->dnode, NULL);
497 bp = nb_running_get_entry(args->dnode, NULL, true);
498 if (bp->echo_mode == echo)
499 return NB_OK;
500
501 bp->echo_mode = echo;
502 bfd_profile_update(bp);
503
504 return NB_OK;
505 }
506
507 /*
508 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-echo-transmission-interval
509 */
510 int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
511 struct nb_cb_modify_args *args)
512 {
513 struct bfd_profile *bp;
514 uint32_t min_tx;
515
516 switch (args->event) {
517 case NB_EV_VALIDATE:
518 min_tx = yang_dnode_get_uint32(args->dnode, NULL);
519 if (min_tx < 10000 || min_tx > 60000000)
520 return NB_ERR_VALIDATION;
521 break;
522
523 case NB_EV_PREPARE:
524 /* NOTHING */
525 break;
526
527 case NB_EV_APPLY:
528 min_tx = yang_dnode_get_uint32(args->dnode, NULL);
529 bp = nb_running_get_entry(args->dnode, NULL, true);
530 if (bp->min_echo_tx == min_tx)
531 return NB_OK;
532
533 bp->min_echo_tx = min_tx;
534 bfd_profile_update(bp);
535 break;
536
537 case NB_EV_ABORT:
538 /* NOTHING */
539 break;
540 }
541
542 return NB_OK;
543 }
544
545 /*
546 * XPath: /frr-bfdd:bfdd/bfd/profile/required-echo-receive-interval
547 */
548 int bfdd_bfd_profile_required_echo_receive_interval_modify(
549 struct nb_cb_modify_args *args)
550 {
551 struct bfd_profile *bp;
552 uint32_t min_rx;
553
554 switch (args->event) {
555 case NB_EV_VALIDATE:
556 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
557 if (min_rx == 0)
558 return NB_OK;
559 if (min_rx < 10000 || min_rx > 60000000)
560 return NB_ERR_VALIDATION;
561 break;
562
563 case NB_EV_PREPARE:
564 /* NOTHING */
565 break;
566
567 case NB_EV_APPLY:
568 min_rx = yang_dnode_get_uint32(args->dnode, NULL);
569 bp = nb_running_get_entry(args->dnode, NULL, true);
570 if (bp->min_echo_rx == min_rx)
571 return NB_OK;
572
573 bp->min_echo_rx = min_rx;
574 bfd_profile_update(bp);
575 break;
576
577 case NB_EV_ABORT:
578 /* NOTHING */
579 break;
580 }
581
582 return NB_OK;
583 }
584
585 /*
586 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop
587 */
588 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args *args)
589 {
590 return bfd_session_create(args, false);
591 }
592
593 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args *args)
594 {
595 return bfd_session_destroy(args->event, args->dnode, false);
596 }
597
598 /*
599 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
600 */
601 int bfdd_bfd_sessions_single_hop_source_addr_modify(
602 struct nb_cb_modify_args *args)
603 {
604 return NB_OK;
605 }
606
607 int bfdd_bfd_sessions_single_hop_source_addr_destroy(
608 struct nb_cb_destroy_args *args)
609 {
610 return NB_OK;
611 }
612
613 /*
614 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/profile
615 */
616 int bfdd_bfd_sessions_single_hop_profile_modify(struct nb_cb_modify_args *args)
617 {
618 struct bfd_session *bs;
619
620 if (args->event != NB_EV_APPLY)
621 return NB_OK;
622
623 bs = nb_running_get_entry(args->dnode, NULL, true);
624 bfd_profile_apply(yang_dnode_get_string(args->dnode, NULL), bs);
625
626 return NB_OK;
627 }
628
629 int bfdd_bfd_sessions_single_hop_profile_destroy(
630 struct nb_cb_destroy_args *args)
631 {
632 struct bfd_session *bs;
633
634 if (args->event != NB_EV_APPLY)
635 return NB_OK;
636
637 bs = nb_running_get_entry(args->dnode, NULL, true);
638 bfd_profile_remove(bs);
639
640 return NB_OK;
641 }
642
643 /*
644 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
645 */
646 int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
647 struct nb_cb_modify_args *args)
648 {
649 uint8_t detection_multiplier = yang_dnode_get_uint8(args->dnode, NULL);
650 struct bfd_session *bs;
651
652 switch (args->event) {
653 case NB_EV_VALIDATE:
654 break;
655
656 case NB_EV_PREPARE:
657 /* NOTHING */
658 break;
659
660 case NB_EV_APPLY:
661 bs = nb_running_get_entry(args->dnode, NULL, true);
662 bs->peer_profile.detection_multiplier = detection_multiplier;
663 bfd_session_apply(bs);
664 break;
665
666 case NB_EV_ABORT:
667 /* NOTHING */
668 break;
669 }
670
671 return NB_OK;
672 }
673
674 /*
675 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
676 */
677 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
678 struct nb_cb_modify_args *args)
679 {
680 uint32_t tx_interval = yang_dnode_get_uint32(args->dnode, NULL);
681 struct bfd_session *bs;
682
683 switch (args->event) {
684 case NB_EV_VALIDATE:
685 if (tx_interval < 10000 || tx_interval > 60000000)
686 return NB_ERR_VALIDATION;
687 break;
688
689 case NB_EV_PREPARE:
690 /* NOTHING */
691 break;
692
693 case NB_EV_APPLY:
694 bs = nb_running_get_entry(args->dnode, NULL, true);
695 if (tx_interval == bs->timers.desired_min_tx)
696 return NB_OK;
697
698 bs->peer_profile.min_tx = tx_interval;
699 bfd_session_apply(bs);
700 break;
701
702 case NB_EV_ABORT:
703 /* NOTHING */
704 break;
705 }
706
707 return NB_OK;
708 }
709
710 /*
711 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
712 */
713 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
714 struct nb_cb_modify_args *args)
715 {
716 uint32_t rx_interval = yang_dnode_get_uint32(args->dnode, NULL);
717 struct bfd_session *bs;
718
719 switch (args->event) {
720 case NB_EV_VALIDATE:
721 if (rx_interval < 10000 || rx_interval > 60000000)
722 return NB_ERR_VALIDATION;
723 break;
724
725 case NB_EV_PREPARE:
726 /* NOTHING */
727 break;
728
729 case NB_EV_APPLY:
730 bs = nb_running_get_entry(args->dnode, NULL, true);
731 if (rx_interval == bs->timers.required_min_rx)
732 return NB_OK;
733
734 bs->peer_profile.min_rx = rx_interval;
735 bfd_session_apply(bs);
736 break;
737
738 case NB_EV_ABORT:
739 /* NOTHING */
740 break;
741 }
742
743 return NB_OK;
744 }
745
746 /*
747 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
748 */
749 int bfdd_bfd_sessions_single_hop_administrative_down_modify(
750 struct nb_cb_modify_args *args)
751 {
752 bool shutdown = yang_dnode_get_bool(args->dnode, NULL);
753 struct bfd_session *bs;
754
755 switch (args->event) {
756 case NB_EV_VALIDATE:
757 case NB_EV_PREPARE:
758 return NB_OK;
759
760 case NB_EV_APPLY:
761 break;
762
763 case NB_EV_ABORT:
764 return NB_OK;
765 }
766
767 bs = nb_running_get_entry(args->dnode, NULL, true);
768 bs->peer_profile.admin_shutdown = shutdown;
769 bfd_session_apply(bs);
770
771 return NB_OK;
772 }
773
774 /*
775 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode
776 */
777 int bfdd_bfd_sessions_single_hop_passive_mode_modify(
778 struct nb_cb_modify_args *args)
779 {
780 struct bfd_session *bs;
781 bool passive;
782
783 switch (args->event) {
784 case NB_EV_VALIDATE:
785 case NB_EV_PREPARE:
786 return NB_OK;
787
788 case NB_EV_APPLY:
789 break;
790
791 case NB_EV_ABORT:
792 return NB_OK;
793 }
794
795 passive = yang_dnode_get_bool(args->dnode, NULL);
796
797 bs = nb_running_get_entry(args->dnode, NULL, true);
798 bs->peer_profile.passive = passive;
799 bfd_session_apply(bs);
800
801 return NB_OK;
802 }
803
804 /*
805 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
806 */
807 int bfdd_bfd_sessions_single_hop_echo_mode_modify(
808 struct nb_cb_modify_args *args)
809 {
810 bool echo = yang_dnode_get_bool(args->dnode, NULL);
811 struct bfd_session *bs;
812
813 switch (args->event) {
814 case NB_EV_VALIDATE:
815 case NB_EV_PREPARE:
816 return NB_OK;
817
818 case NB_EV_APPLY:
819 break;
820
821 case NB_EV_ABORT:
822 return NB_OK;
823 }
824
825 bs = nb_running_get_entry(args->dnode, NULL, true);
826 bs->peer_profile.echo_mode = echo;
827 bfd_session_apply(bs);
828
829 return NB_OK;
830 }
831
832 /*
833 * XPath:
834 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
835 */
836 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
837 struct nb_cb_modify_args *args)
838 {
839 uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
840 struct bfd_session *bs;
841
842 switch (args->event) {
843 case NB_EV_VALIDATE:
844 if (echo_interval < 10000 || echo_interval > 60000000)
845 return NB_ERR_VALIDATION;
846 break;
847
848 case NB_EV_PREPARE:
849 /* NOTHING */
850 break;
851
852 case NB_EV_APPLY:
853 bs = nb_running_get_entry(args->dnode, NULL, true);
854 if (echo_interval == bs->timers.desired_min_echo_tx)
855 return NB_OK;
856
857 bs->peer_profile.min_echo_tx = echo_interval;
858 bfd_session_apply(bs);
859 break;
860
861 case NB_EV_ABORT:
862 /* NOTHING */
863 break;
864 }
865
866 return NB_OK;
867 }
868
869 /*
870 * XPath:
871 * /frr-bfdd:bfdd/bfd/sessions/single-hop/required-echo-receive-interval
872 */
873 int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
874 struct nb_cb_modify_args *args)
875 {
876 uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
877 struct bfd_session *bs;
878
879 switch (args->event) {
880 case NB_EV_VALIDATE:
881 if (echo_interval == 0)
882 return NB_OK;
883 if (echo_interval < 10000 || echo_interval > 60000000)
884 return NB_ERR_VALIDATION;
885 break;
886
887 case NB_EV_PREPARE:
888 /* NOTHING */
889 break;
890
891 case NB_EV_APPLY:
892 bs = nb_running_get_entry(args->dnode, NULL, true);
893 if (echo_interval == bs->timers.required_min_echo_rx)
894 return NB_OK;
895
896 bs->peer_profile.min_echo_rx = echo_interval;
897 bfd_session_apply(bs);
898 break;
899
900 case NB_EV_ABORT:
901 /* NOTHING */
902 break;
903 }
904
905 return NB_OK;
906 }
907
908 /*
909 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
910 */
911 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args *args)
912 {
913 return bfd_session_create(args, true);
914 }
915
916 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args *args)
917 {
918 return bfd_session_destroy(args->event, args->dnode, true);
919 }
920
921 /*
922 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl
923 */
924 int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
925 struct nb_cb_modify_args *args)
926 {
927 struct bfd_session *bs;
928
929 switch (args->event) {
930 case NB_EV_VALIDATE:
931 case NB_EV_PREPARE:
932 return NB_OK;
933
934 case NB_EV_APPLY:
935 break;
936
937 case NB_EV_ABORT:
938 return NB_OK;
939 }
940
941 bs = nb_running_get_entry(args->dnode, NULL, true);
942 bs->peer_profile.minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
943 bfd_session_apply(bs);
944
945 return NB_OK;
946 }
947
948 int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
949 struct nb_cb_destroy_args *args)
950 {
951 struct bfd_session *bs;
952
953 switch (args->event) {
954 case NB_EV_VALIDATE:
955 case NB_EV_PREPARE:
956 return NB_OK;
957
958 case NB_EV_APPLY:
959 break;
960
961 case NB_EV_ABORT:
962 return NB_OK;
963 }
964
965 bs = nb_running_get_entry(args->dnode, NULL, true);
966 bs->peer_profile.minimum_ttl = BFD_DEF_MHOP_TTL;
967 bfd_session_apply(bs);
968
969 return NB_OK;
970 }