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