]>
git.proxmox.com Git - mirror_frr.git/blob - bfdd/bfdd_nb_config.c
2 * BFD daemon northbound implementation.
4 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
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.
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.
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
26 #include "lib/northbound.h"
34 static void bfd_session_get_key(bool mhop
, const struct lyd_node
*dnode
,
37 const char *ifname
= NULL
, *vrfname
= NULL
;
38 struct sockaddr_any psa
, lsa
;
40 /* Required destination parameter. */
41 strtosa(yang_dnode_get_string(dnode
, "./dest-addr"), &psa
);
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
);
48 vrfname
= yang_dnode_get_string(dnode
, "./vrf");
51 ifname
= yang_dnode_get_string(dnode
, "./interface");
52 if (strcmp(ifname
, "*") == 0)
56 /* Generate the corresponding key. */
57 gen_bfd_key(bk
, &psa
, &lsa
, mhop
, ifname
, vrfname
);
65 static int session_iter_cb(const struct lyd_node
*dnode
, void *arg
)
67 struct session_iter
*iter
= arg
;
70 ifname
= yang_dnode_get_string(dnode
, "./interface");
72 if (strmatch(ifname
, "*"))
73 iter
->wildcard
= true;
77 return YANG_ITER_CONTINUE
;
80 static int bfd_session_create(struct nb_cb_create_args
*args
, bool mhop
)
82 const struct lyd_node
*sess_dnode
;
83 struct session_iter iter
;
84 struct bfd_session
*bs
;
91 switch (args
->event
) {
93 yang_dnode_get_prefix(&p
, args
->dnode
, "./dest-addr");
97 * Do not allow IPv6 link-local address for multihop.
99 if (p
.family
== AF_INET6
100 && IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
102 args
->errmsg
, args
->errmsg_len
,
103 "Cannot use link-local address for multihop sessions");
104 return NB_ERR_VALIDATION
;
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.
114 ifname
= yang_dnode_get_string(args
->dnode
, "./interface");
116 if (p
.family
== AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)
117 && strcmp(ifname
, "*") == 0) {
119 args
->errmsg
, args
->errmsg_len
,
120 "When using link-local you must specify an interface");
121 return NB_ERR_VALIDATION
;
125 iter
.wildcard
= false;
127 sess_dnode
= yang_dnode_get_parent(args
->dnode
, "sessions");
129 dest
= yang_dnode_get_string(args
->dnode
, "./dest-addr");
130 vrfname
= yang_dnode_get_string(args
->dnode
, "./vrf");
132 yang_dnode_iterate(session_iter_cb
, &iter
, sess_dnode
,
133 "./single-hop[dest-addr='%s'][vrf='%s']",
136 if (iter
.wildcard
&& iter
.count
> 1) {
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
;
145 bfd_session_get_key(mhop
, args
->dnode
, &bk
);
146 bs
= bfd_key_lookup(bk
);
148 /* This session was already configured by another daemon. */
150 /* Now it is configured also by CLI. */
151 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
154 args
->resource
->ptr
= bs
;
158 bs
= bfd_session_new();
160 /* Fill the session key. */
161 bfd_session_get_key(mhop
, args
->dnode
, &bs
->key
);
163 /* Set configuration flags. */
165 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
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
);
171 args
->resource
->ptr
= bs
;
175 bs
= args
->resource
->ptr
;
177 /* Only attempt to registrate if freshly allocated. */
178 if (bs
->discrs
.my_discr
== 0 && bs_registrate(bs
) == NULL
)
179 return NB_ERR_RESOURCE
;
181 nb_running_set_entry(args
->dnode
, bs
);
185 bs
= args
->resource
->ptr
;
186 if (bs
->refcount
<= 1)
187 bfd_session_free(bs
);
194 static int bfd_session_destroy(enum nb_event event
,
195 const struct lyd_node
*dnode
, bool mhop
)
197 struct bfd_session
*bs
;
202 bfd_session_get_key(mhop
, dnode
, &bk
);
203 if (bfd_key_lookup(bk
) == NULL
)
204 return NB_ERR_INCONSISTENCY
;
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)
217 UNSET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
219 /* There are still daemons using it. */
220 if (bs
->refcount
> 0)
223 bfd_session_free(bs
);
235 * XPath: /frr-bfdd:bfdd/bfd
237 int bfdd_bfd_create(struct nb_cb_create_args
*args
)
239 if (args
->event
!= NB_EV_APPLY
)
243 * Set any non-NULL value to be able to call
244 * nb_running_unset_entry in bfdd_bfd_destroy.
246 nb_running_set_entry(args
->dnode
, (void *)0x1);
251 int bfdd_bfd_destroy(struct nb_cb_destroy_args
*args
)
253 switch (args
->event
) {
264 * We need to call this to unset pointers from
265 * the child nodes - sessions and profiles.
267 nb_running_unset_entry(args
->dnode
);
269 bfd_sessions_remove_manual();
270 bfd_profiles_remove();
282 * XPath: /frr-bfdd:bfdd/bfd/profile
284 int bfdd_bfd_profile_create(struct nb_cb_create_args
*args
)
286 struct bfd_profile
*bp
;
289 if (args
->event
!= NB_EV_APPLY
)
292 name
= yang_dnode_get_string(args
->dnode
, "./name");
293 bp
= bfd_profile_new(name
);
294 nb_running_set_entry(args
->dnode
, bp
);
299 int bfdd_bfd_profile_destroy(struct nb_cb_destroy_args
*args
)
301 struct bfd_profile
*bp
;
303 if (args
->event
!= NB_EV_APPLY
)
306 bp
= nb_running_unset_entry(args
->dnode
);
307 bfd_profile_free(bp
);
313 * XPath: /frr-bfdd:bfdd/bfd/profile/detection-multiplier
315 int bfdd_bfd_profile_detection_multiplier_modify(struct nb_cb_modify_args
*args
)
317 struct bfd_profile
*bp
;
319 if (args
->event
!= NB_EV_APPLY
)
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
);
330 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-transmission-interval
332 int bfdd_bfd_profile_desired_transmission_interval_modify(
333 struct nb_cb_modify_args
*args
)
335 struct bfd_profile
*bp
;
338 switch (args
->event
) {
340 min_tx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
341 if (min_tx
< 10000 || min_tx
> 60000000)
342 return NB_ERR_VALIDATION
;
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
)
356 bfd_profile_update(bp
);
368 * XPath: /frr-bfdd:bfdd/bfd/profile/required-receive-interval
370 int bfdd_bfd_profile_required_receive_interval_modify(
371 struct nb_cb_modify_args
*args
)
373 struct bfd_profile
*bp
;
376 switch (args
->event
) {
378 min_rx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
379 if (min_rx
< 10000 || min_rx
> 60000000)
380 return NB_ERR_VALIDATION
;
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
)
394 bfd_profile_update(bp
);
406 * XPath: /frr-bfdd:bfdd/bfd/profile/administrative-down
408 int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args
*args
)
410 struct bfd_profile
*bp
;
413 if (args
->event
!= NB_EV_APPLY
)
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
)
421 bp
->admin_shutdown
= shutdown
;
422 bfd_profile_update(bp
);
428 * XPath: /frr-bfdd:bfdd/bfd/profile/passive-mode
430 int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args
*args
)
432 struct bfd_profile
*bp
;
435 if (args
->event
!= NB_EV_APPLY
)
438 passive
= yang_dnode_get_bool(args
->dnode
, NULL
);
439 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
440 if (bp
->passive
== passive
)
443 bp
->passive
= passive
;
444 bfd_profile_update(bp
);
450 * XPath: /frr-bfdd:bfdd/bfd/profile/minimum-ttl
452 int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args
*args
)
454 struct bfd_profile
*bp
;
457 if (args
->event
!= NB_EV_APPLY
)
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
)
465 bp
->minimum_ttl
= minimum_ttl
;
466 bfd_profile_update(bp
);
471 int bfdd_bfd_profile_minimum_ttl_destroy(struct nb_cb_destroy_args
*args
)
473 struct bfd_profile
*bp
;
475 if (args
->event
!= NB_EV_APPLY
)
478 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
479 bp
->minimum_ttl
= BFD_DEF_MHOP_TTL
;
480 bfd_profile_update(bp
);
486 * XPath: /frr-bfdd:bfdd/bfd/profile/echo-mode
488 int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args
*args
)
490 struct bfd_profile
*bp
;
493 if (args
->event
!= NB_EV_APPLY
)
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
)
501 bp
->echo_mode
= echo
;
502 bfd_profile_update(bp
);
508 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-echo-transmission-interval
510 int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
511 struct nb_cb_modify_args
*args
)
513 struct bfd_profile
*bp
;
516 switch (args
->event
) {
518 min_tx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
519 if (min_tx
< 10000 || min_tx
> 60000000)
520 return NB_ERR_VALIDATION
;
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
)
533 bp
->min_echo_tx
= min_tx
;
534 bfd_profile_update(bp
);
546 * XPath: /frr-bfdd:bfdd/bfd/profile/required-echo-receive-interval
548 int bfdd_bfd_profile_required_echo_receive_interval_modify(
549 struct nb_cb_modify_args
*args
)
551 struct bfd_profile
*bp
;
554 switch (args
->event
) {
556 min_rx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
559 if (min_rx
< 10000 || min_rx
> 60000000)
560 return NB_ERR_VALIDATION
;
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
)
573 bp
->min_echo_rx
= min_rx
;
574 bfd_profile_update(bp
);
586 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop
588 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args
*args
)
590 return bfd_session_create(args
, false);
593 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args
*args
)
595 return bfd_session_destroy(args
->event
, args
->dnode
, false);
599 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
601 int bfdd_bfd_sessions_single_hop_source_addr_modify(
602 struct nb_cb_modify_args
*args
)
607 int bfdd_bfd_sessions_single_hop_source_addr_destroy(
608 struct nb_cb_destroy_args
*args
)
614 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/profile
616 int bfdd_bfd_sessions_single_hop_profile_modify(struct nb_cb_modify_args
*args
)
618 struct bfd_session
*bs
;
620 if (args
->event
!= NB_EV_APPLY
)
623 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
624 bfd_profile_apply(yang_dnode_get_string(args
->dnode
, NULL
), bs
);
629 int bfdd_bfd_sessions_single_hop_profile_destroy(
630 struct nb_cb_destroy_args
*args
)
632 struct bfd_session
*bs
;
634 if (args
->event
!= NB_EV_APPLY
)
637 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
638 bfd_profile_remove(bs
);
644 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
646 int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
647 struct nb_cb_modify_args
*args
)
649 uint8_t detection_multiplier
= yang_dnode_get_uint8(args
->dnode
, NULL
);
650 struct bfd_session
*bs
;
652 switch (args
->event
) {
661 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
662 bs
->peer_profile
.detection_multiplier
= detection_multiplier
;
663 bfd_session_apply(bs
);
675 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
677 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
678 struct nb_cb_modify_args
*args
)
680 uint32_t tx_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
681 struct bfd_session
*bs
;
683 switch (args
->event
) {
685 if (tx_interval
< 10000 || tx_interval
> 60000000)
686 return NB_ERR_VALIDATION
;
694 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
695 if (tx_interval
== bs
->timers
.desired_min_tx
)
698 bs
->peer_profile
.min_tx
= tx_interval
;
699 bfd_session_apply(bs
);
711 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
713 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
714 struct nb_cb_modify_args
*args
)
716 uint32_t rx_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
717 struct bfd_session
*bs
;
719 switch (args
->event
) {
721 if (rx_interval
< 10000 || rx_interval
> 60000000)
722 return NB_ERR_VALIDATION
;
730 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
731 if (rx_interval
== bs
->timers
.required_min_rx
)
734 bs
->peer_profile
.min_rx
= rx_interval
;
735 bfd_session_apply(bs
);
747 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
749 int bfdd_bfd_sessions_single_hop_administrative_down_modify(
750 struct nb_cb_modify_args
*args
)
752 bool shutdown
= yang_dnode_get_bool(args
->dnode
, NULL
);
753 struct bfd_session
*bs
;
755 switch (args
->event
) {
767 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
768 bs
->peer_profile
.admin_shutdown
= shutdown
;
769 bfd_session_apply(bs
);
775 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode
777 int bfdd_bfd_sessions_single_hop_passive_mode_modify(
778 struct nb_cb_modify_args
*args
)
780 struct bfd_session
*bs
;
783 switch (args
->event
) {
795 passive
= yang_dnode_get_bool(args
->dnode
, NULL
);
797 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
798 bs
->peer_profile
.passive
= passive
;
799 bfd_session_apply(bs
);
805 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
807 int bfdd_bfd_sessions_single_hop_echo_mode_modify(
808 struct nb_cb_modify_args
*args
)
810 bool echo
= yang_dnode_get_bool(args
->dnode
, NULL
);
811 struct bfd_session
*bs
;
813 switch (args
->event
) {
825 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
826 bs
->peer_profile
.echo_mode
= echo
;
827 bfd_session_apply(bs
);
834 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
836 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
837 struct nb_cb_modify_args
*args
)
839 uint32_t echo_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
840 struct bfd_session
*bs
;
842 switch (args
->event
) {
844 if (echo_interval
< 10000 || echo_interval
> 60000000)
845 return NB_ERR_VALIDATION
;
853 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
854 if (echo_interval
== bs
->timers
.desired_min_echo_tx
)
857 bs
->peer_profile
.min_echo_tx
= echo_interval
;
858 bfd_session_apply(bs
);
871 * /frr-bfdd:bfdd/bfd/sessions/single-hop/required-echo-receive-interval
873 int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
874 struct nb_cb_modify_args
*args
)
876 uint32_t echo_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
877 struct bfd_session
*bs
;
879 switch (args
->event
) {
881 if (echo_interval
== 0)
883 if (echo_interval
< 10000 || echo_interval
> 60000000)
884 return NB_ERR_VALIDATION
;
892 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
893 if (echo_interval
== bs
->timers
.required_min_echo_rx
)
896 bs
->peer_profile
.min_echo_rx
= echo_interval
;
897 bfd_session_apply(bs
);
909 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
911 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args
*args
)
913 return bfd_session_create(args
, true);
916 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args
*args
)
918 return bfd_session_destroy(args
->event
, args
->dnode
, true);
922 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl
924 int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
925 struct nb_cb_modify_args
*args
)
927 struct bfd_session
*bs
;
929 switch (args
->event
) {
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
);
948 int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
949 struct nb_cb_destroy_args
*args
)
951 struct bfd_session
*bs
;
953 switch (args
->event
) {
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
);