]>
git.proxmox.com Git - mirror_frr.git/blob - bfdd/bfdd_nb_config.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * BFD daemon northbound implementation.
5 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
12 #include "lib/northbound.h"
20 static void bfd_session_get_key(bool mhop
, const struct lyd_node
*dnode
,
23 const char *ifname
= NULL
, *vrfname
= NULL
;
24 struct sockaddr_any psa
, lsa
;
26 /* Required destination parameter. */
27 strtosa(yang_dnode_get_string(dnode
, "./dest-addr"), &psa
);
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
);
34 vrfname
= yang_dnode_get_string(dnode
, "./vrf");
37 ifname
= yang_dnode_get_string(dnode
, "./interface");
38 if (strcmp(ifname
, "*") == 0)
42 /* Generate the corresponding key. */
43 gen_bfd_key(bk
, &psa
, &lsa
, mhop
, ifname
, vrfname
);
51 static int session_iter_cb(const struct lyd_node
*dnode
, void *arg
)
53 struct session_iter
*iter
= arg
;
56 ifname
= yang_dnode_get_string(dnode
, "./interface");
58 if (strmatch(ifname
, "*"))
59 iter
->wildcard
= true;
63 return YANG_ITER_CONTINUE
;
66 static int bfd_session_create(struct nb_cb_create_args
*args
, bool mhop
)
68 const struct lyd_node
*sess_dnode
;
69 struct session_iter iter
;
70 struct bfd_session
*bs
;
77 switch (args
->event
) {
79 yang_dnode_get_prefix(&p
, args
->dnode
, "./dest-addr");
83 * Do not allow IPv6 link-local address for multihop.
85 if (p
.family
== AF_INET6
86 && IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
88 args
->errmsg
, args
->errmsg_len
,
89 "Cannot use link-local address for multihop sessions");
90 return NB_ERR_VALIDATION
;
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.
100 ifname
= yang_dnode_get_string(args
->dnode
, "./interface");
102 if (p
.family
== AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)
103 && strcmp(ifname
, "*") == 0) {
105 args
->errmsg
, args
->errmsg_len
,
106 "When using link-local you must specify an interface");
107 return NB_ERR_VALIDATION
;
111 iter
.wildcard
= false;
113 sess_dnode
= yang_dnode_get_parent(args
->dnode
, "sessions");
115 dest
= yang_dnode_get_string(args
->dnode
, "./dest-addr");
116 vrfname
= yang_dnode_get_string(args
->dnode
, "./vrf");
118 yang_dnode_iterate(session_iter_cb
, &iter
, sess_dnode
,
119 "./single-hop[dest-addr='%s'][vrf='%s']",
122 if (iter
.wildcard
&& iter
.count
> 1) {
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
;
131 bfd_session_get_key(mhop
, args
->dnode
, &bk
);
132 bs
= bfd_key_lookup(bk
);
134 /* This session was already configured by another daemon. */
136 /* Now it is configured also by CLI. */
137 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
140 args
->resource
->ptr
= bs
;
144 bs
= bfd_session_new();
146 /* Fill the session key. */
147 bfd_session_get_key(mhop
, args
->dnode
, &bs
->key
);
149 /* Set configuration flags. */
151 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
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
);
157 args
->resource
->ptr
= bs
;
161 bs
= args
->resource
->ptr
;
163 /* Only attempt to registrate if freshly allocated. */
164 if (bs
->discrs
.my_discr
== 0 && bs_registrate(bs
) == NULL
)
165 return NB_ERR_RESOURCE
;
167 nb_running_set_entry(args
->dnode
, bs
);
171 bs
= args
->resource
->ptr
;
172 if (bs
->refcount
<= 1)
173 bfd_session_free(bs
);
180 static int bfd_session_destroy(enum nb_event event
,
181 const struct lyd_node
*dnode
, bool mhop
)
183 struct bfd_session
*bs
;
188 bfd_session_get_key(mhop
, dnode
, &bk
);
189 if (bfd_key_lookup(bk
) == NULL
)
190 return NB_ERR_INCONSISTENCY
;
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)
203 UNSET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
205 /* There are still daemons using it. */
206 if (bs
->refcount
> 0)
209 bfd_session_free(bs
);
221 * XPath: /frr-bfdd:bfdd/bfd
223 int bfdd_bfd_create(struct nb_cb_create_args
*args
)
225 if (args
->event
!= NB_EV_APPLY
)
229 * Set any non-NULL value to be able to call
230 * nb_running_unset_entry in bfdd_bfd_destroy.
232 nb_running_set_entry(args
->dnode
, (void *)0x1);
237 int bfdd_bfd_destroy(struct nb_cb_destroy_args
*args
)
239 switch (args
->event
) {
250 * We need to call this to unset pointers from
251 * the child nodes - sessions and profiles.
253 nb_running_unset_entry(args
->dnode
);
255 bfd_sessions_remove_manual();
256 bfd_profiles_remove();
268 * XPath: /frr-bfdd:bfdd/bfd/profile
270 int bfdd_bfd_profile_create(struct nb_cb_create_args
*args
)
272 struct bfd_profile
*bp
;
275 if (args
->event
!= NB_EV_APPLY
)
278 name
= yang_dnode_get_string(args
->dnode
, "./name");
279 bp
= bfd_profile_new(name
);
280 nb_running_set_entry(args
->dnode
, bp
);
285 int bfdd_bfd_profile_destroy(struct nb_cb_destroy_args
*args
)
287 struct bfd_profile
*bp
;
289 if (args
->event
!= NB_EV_APPLY
)
292 bp
= nb_running_unset_entry(args
->dnode
);
293 bfd_profile_free(bp
);
299 * XPath: /frr-bfdd:bfdd/bfd/profile/detection-multiplier
301 int bfdd_bfd_profile_detection_multiplier_modify(struct nb_cb_modify_args
*args
)
303 struct bfd_profile
*bp
;
305 if (args
->event
!= NB_EV_APPLY
)
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
);
316 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-transmission-interval
318 int bfdd_bfd_profile_desired_transmission_interval_modify(
319 struct nb_cb_modify_args
*args
)
321 struct bfd_profile
*bp
;
323 switch (args
->event
) {
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
);
346 * XPath: /frr-bfdd:bfdd/bfd/profile/required-receive-interval
348 int bfdd_bfd_profile_required_receive_interval_modify(
349 struct nb_cb_modify_args
*args
)
351 struct bfd_profile
*bp
;
353 switch (args
->event
) {
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
);
376 * XPath: /frr-bfdd:bfdd/bfd/profile/administrative-down
378 int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args
*args
)
380 struct bfd_profile
*bp
;
382 if (args
->event
!= NB_EV_APPLY
)
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
);
393 * XPath: /frr-bfdd:bfdd/bfd/profile/passive-mode
395 int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args
*args
)
397 struct bfd_profile
*bp
;
399 if (args
->event
!= NB_EV_APPLY
)
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
);
410 * XPath: /frr-bfdd:bfdd/bfd/profile/minimum-ttl
412 int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args
*args
)
414 struct bfd_profile
*bp
;
416 if (args
->event
!= NB_EV_APPLY
)
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
);
426 int bfdd_bfd_profile_minimum_ttl_destroy(struct nb_cb_destroy_args
*args
)
428 struct bfd_profile
*bp
;
430 if (args
->event
!= NB_EV_APPLY
)
433 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
434 bp
->minimum_ttl
= BFD_DEF_MHOP_TTL
;
435 bfd_profile_update(bp
);
441 * XPath: /frr-bfdd:bfdd/bfd/profile/echo-mode
443 int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args
*args
)
445 struct bfd_profile
*bp
;
448 if (args
->event
!= NB_EV_APPLY
)
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
)
456 bp
->echo_mode
= echo
;
457 bfd_profile_update(bp
);
463 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-echo-transmission-interval
465 int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
466 struct nb_cb_modify_args
*args
)
468 struct bfd_profile
*bp
;
470 switch (args
->event
) {
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
);
493 * XPath: /frr-bfdd:bfdd/bfd/profile/required-echo-receive-interval
495 int bfdd_bfd_profile_required_echo_receive_interval_modify(
496 struct nb_cb_modify_args
*args
)
498 struct bfd_profile
*bp
;
500 switch (args
->event
) {
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
);
523 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop
525 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args
*args
)
527 return bfd_session_create(args
, false);
530 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args
*args
)
532 return bfd_session_destroy(args
->event
, args
->dnode
, false);
536 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
538 int bfdd_bfd_sessions_single_hop_source_addr_modify(
539 struct nb_cb_modify_args
*args
)
544 int bfdd_bfd_sessions_single_hop_source_addr_destroy(
545 struct nb_cb_destroy_args
*args
)
551 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/profile
553 int bfdd_bfd_sessions_single_hop_profile_modify(struct nb_cb_modify_args
*args
)
555 struct bfd_session
*bs
;
557 if (args
->event
!= NB_EV_APPLY
)
560 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
561 bfd_profile_apply(yang_dnode_get_string(args
->dnode
, NULL
), bs
);
566 int bfdd_bfd_sessions_single_hop_profile_destroy(
567 struct nb_cb_destroy_args
*args
)
569 struct bfd_session
*bs
;
571 if (args
->event
!= NB_EV_APPLY
)
574 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
575 bfd_profile_remove(bs
);
581 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
583 int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
584 struct nb_cb_modify_args
*args
)
586 uint8_t detection_multiplier
= yang_dnode_get_uint8(args
->dnode
, NULL
);
587 struct bfd_session
*bs
;
589 switch (args
->event
) {
598 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
599 bs
->peer_profile
.detection_multiplier
= detection_multiplier
;
600 bfd_session_apply(bs
);
612 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
614 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
615 struct nb_cb_modify_args
*args
)
617 struct bfd_session
*bs
;
619 switch (args
->event
) {
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
);
643 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
645 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
646 struct nb_cb_modify_args
*args
)
648 struct bfd_session
*bs
;
650 switch (args
->event
) {
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
);
674 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
676 int bfdd_bfd_sessions_single_hop_administrative_down_modify(
677 struct nb_cb_modify_args
*args
)
679 bool shutdown
= yang_dnode_get_bool(args
->dnode
, NULL
);
680 struct bfd_session
*bs
;
682 switch (args
->event
) {
694 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
695 bs
->peer_profile
.admin_shutdown
= shutdown
;
696 bfd_session_apply(bs
);
702 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode
704 int bfdd_bfd_sessions_single_hop_passive_mode_modify(
705 struct nb_cb_modify_args
*args
)
707 struct bfd_session
*bs
;
710 switch (args
->event
) {
722 passive
= yang_dnode_get_bool(args
->dnode
, NULL
);
724 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
725 bs
->peer_profile
.passive
= passive
;
726 bfd_session_apply(bs
);
732 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
734 int bfdd_bfd_sessions_single_hop_echo_mode_modify(
735 struct nb_cb_modify_args
*args
)
737 bool echo
= yang_dnode_get_bool(args
->dnode
, NULL
);
738 struct bfd_session
*bs
;
740 switch (args
->event
) {
752 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
753 bs
->peer_profile
.echo_mode
= echo
;
754 bfd_session_apply(bs
);
761 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
763 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
764 struct nb_cb_modify_args
*args
)
766 struct bfd_session
*bs
;
768 switch (args
->event
) {
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
);
793 * /frr-bfdd:bfdd/bfd/sessions/single-hop/required-echo-receive-interval
795 int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
796 struct nb_cb_modify_args
*args
)
798 struct bfd_session
*bs
;
800 switch (args
->event
) {
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
);
824 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
826 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args
*args
)
828 return bfd_session_create(args
, true);
831 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args
*args
)
833 return bfd_session_destroy(args
->event
, args
->dnode
, true);
837 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl
839 int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
840 struct nb_cb_modify_args
*args
)
842 struct bfd_session
*bs
;
844 switch (args
->event
) {
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
);
863 int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
864 struct nb_cb_destroy_args
*args
)
866 struct bfd_session
*bs
;
868 switch (args
->event
) {
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
);