]>
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 ifname
= yang_dnode_get_string(dnode
, "./interface");
49 vrfname
= yang_dnode_get_string(dnode
, "./vrf");
51 if (strcmp(ifname
, "*") == 0)
54 /* Generate the corresponding key. */
55 gen_bfd_key(bk
, &psa
, &lsa
, mhop
, ifname
, vrfname
);
63 static int session_iter_cb(const struct lyd_node
*dnode
, void *arg
)
65 struct session_iter
*iter
= arg
;
68 ifname
= yang_dnode_get_string(dnode
, "./interface");
70 if (strmatch(ifname
, "*"))
71 iter
->wildcard
= true;
75 return YANG_ITER_CONTINUE
;
78 static int bfd_session_create(struct nb_cb_create_args
*args
, bool mhop
)
80 const struct lyd_node
*sess_dnode
;
81 struct session_iter iter
;
82 struct bfd_session
*bs
;
90 switch (args
->event
) {
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.
97 yang_dnode_get_prefix(&p
, args
->dnode
, "./dest-addr");
99 ifname
= yang_dnode_get_string(args
->dnode
, "./interface");
101 if (p
.family
== AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)
102 && strcmp(ifname
, "*") == 0) {
104 args
->errmsg
, args
->errmsg_len
,
105 "When using link-local you must specify an interface");
106 return NB_ERR_VALIDATION
;
110 iter
.wildcard
= false;
112 sess_dnode
= yang_dnode_get_parent(args
->dnode
, "sessions");
114 dest
= yang_dnode_get_string(args
->dnode
, "./dest-addr");
115 vrfname
= yang_dnode_get_string(args
->dnode
, "./vrf");
118 source
= yang_dnode_get_string(args
->dnode
, "./source-addr");
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
);
124 yang_dnode_iterate(session_iter_cb
, &iter
, sess_dnode
,
125 "./single-hop[dest-addr='%s'][vrf='%s']",
129 if (iter
.wildcard
&& iter
.count
> 1) {
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
;
138 bfd_session_get_key(mhop
, args
->dnode
, &bk
);
139 bs
= bfd_key_lookup(bk
);
141 /* This session was already configured by another daemon. */
143 /* Now it is configured also by CLI. */
144 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
147 args
->resource
->ptr
= bs
;
151 bs
= bfd_session_new();
153 /* Fill the session key. */
154 bfd_session_get_key(mhop
, args
->dnode
, &bs
->key
);
156 /* Set configuration flags. */
158 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
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
);
164 args
->resource
->ptr
= bs
;
168 bs
= args
->resource
->ptr
;
170 /* Only attempt to registrate if freshly allocated. */
171 if (bs
->discrs
.my_discr
== 0 && bs_registrate(bs
) == NULL
)
172 return NB_ERR_RESOURCE
;
174 nb_running_set_entry(args
->dnode
, bs
);
178 bs
= args
->resource
->ptr
;
179 if (bs
->refcount
<= 1)
180 bfd_session_free(bs
);
187 static int bfd_session_destroy(enum nb_event event
,
188 const struct lyd_node
*dnode
, bool mhop
)
190 struct bfd_session
*bs
;
195 bfd_session_get_key(mhop
, dnode
, &bk
);
196 if (bfd_key_lookup(bk
) == NULL
)
197 return NB_ERR_INCONSISTENCY
;
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)
210 UNSET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
212 /* There are still daemons using it. */
213 if (bs
->refcount
> 0)
216 bfd_session_free(bs
);
228 * XPath: /frr-bfdd:bfdd/bfd
230 int bfdd_bfd_create(struct nb_cb_create_args
*args
)
232 if (args
->event
!= NB_EV_APPLY
)
236 * Set any non-NULL value to be able to call
237 * nb_running_unset_entry in bfdd_bfd_destroy.
239 nb_running_set_entry(args
->dnode
, (void *)0x1);
244 int bfdd_bfd_destroy(struct nb_cb_destroy_args
*args
)
246 switch (args
->event
) {
257 * We need to call this to unset pointers from
258 * the child nodes - sessions and profiles.
260 nb_running_unset_entry(args
->dnode
);
262 bfd_sessions_remove_manual();
263 bfd_profiles_remove();
275 * XPath: /frr-bfdd:bfdd/bfd/profile
277 int bfdd_bfd_profile_create(struct nb_cb_create_args
*args
)
279 struct bfd_profile
*bp
;
282 if (args
->event
!= NB_EV_APPLY
)
285 name
= yang_dnode_get_string(args
->dnode
, "./name");
286 bp
= bfd_profile_new(name
);
287 nb_running_set_entry(args
->dnode
, bp
);
292 int bfdd_bfd_profile_destroy(struct nb_cb_destroy_args
*args
)
294 struct bfd_profile
*bp
;
296 if (args
->event
!= NB_EV_APPLY
)
299 bp
= nb_running_unset_entry(args
->dnode
);
300 bfd_profile_free(bp
);
306 * XPath: /frr-bfdd:bfdd/bfd/profile/detection-multiplier
308 int bfdd_bfd_profile_detection_multiplier_modify(struct nb_cb_modify_args
*args
)
310 struct bfd_profile
*bp
;
312 if (args
->event
!= NB_EV_APPLY
)
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
);
323 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-transmission-interval
325 int bfdd_bfd_profile_desired_transmission_interval_modify(
326 struct nb_cb_modify_args
*args
)
328 struct bfd_profile
*bp
;
331 switch (args
->event
) {
333 min_tx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
334 if (min_tx
< 10000 || min_tx
> 60000000)
335 return NB_ERR_VALIDATION
;
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
)
349 bfd_profile_update(bp
);
361 * XPath: /frr-bfdd:bfdd/bfd/profile/required-receive-interval
363 int bfdd_bfd_profile_required_receive_interval_modify(
364 struct nb_cb_modify_args
*args
)
366 struct bfd_profile
*bp
;
369 switch (args
->event
) {
371 min_rx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
372 if (min_rx
< 10000 || min_rx
> 60000000)
373 return NB_ERR_VALIDATION
;
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
)
387 bfd_profile_update(bp
);
399 * XPath: /frr-bfdd:bfdd/bfd/profile/administrative-down
401 int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args
*args
)
403 struct bfd_profile
*bp
;
406 if (args
->event
!= NB_EV_APPLY
)
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
)
414 bp
->admin_shutdown
= shutdown
;
415 bfd_profile_update(bp
);
421 * XPath: /frr-bfdd:bfdd/bfd/profile/passive-mode
423 int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args
*args
)
425 struct bfd_profile
*bp
;
428 if (args
->event
!= NB_EV_APPLY
)
431 passive
= yang_dnode_get_bool(args
->dnode
, NULL
);
432 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
433 if (bp
->passive
== passive
)
436 bp
->passive
= passive
;
437 bfd_profile_update(bp
);
443 * XPath: /frr-bfdd:bfdd/bfd/profile/minimum-ttl
445 int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args
*args
)
447 struct bfd_profile
*bp
;
450 if (args
->event
!= NB_EV_APPLY
)
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
)
458 bp
->minimum_ttl
= minimum_ttl
;
459 bfd_profile_update(bp
);
464 int bfdd_bfd_profile_minimum_ttl_destroy(struct nb_cb_destroy_args
*args
)
466 struct bfd_profile
*bp
;
468 if (args
->event
!= NB_EV_APPLY
)
471 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
472 bp
->minimum_ttl
= BFD_DEF_MHOP_TTL
;
473 bfd_profile_update(bp
);
479 * XPath: /frr-bfdd:bfdd/bfd/profile/echo-mode
481 int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args
*args
)
483 struct bfd_profile
*bp
;
486 if (args
->event
!= NB_EV_APPLY
)
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
)
494 bp
->echo_mode
= echo
;
495 bfd_profile_update(bp
);
501 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-echo-transmission-interval
503 int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
504 struct nb_cb_modify_args
*args
)
506 struct bfd_profile
*bp
;
509 switch (args
->event
) {
511 min_tx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
512 if (min_tx
< 10000 || min_tx
> 60000000)
513 return NB_ERR_VALIDATION
;
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
)
526 bp
->min_echo_tx
= min_tx
;
527 bfd_profile_update(bp
);
539 * XPath: /frr-bfdd:bfdd/bfd/profile/required-echo-receive-interval
541 int bfdd_bfd_profile_required_echo_receive_interval_modify(
542 struct nb_cb_modify_args
*args
)
544 struct bfd_profile
*bp
;
547 switch (args
->event
) {
549 min_rx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
552 if (min_rx
< 10000 || min_rx
> 60000000)
553 return NB_ERR_VALIDATION
;
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
)
566 bp
->min_echo_rx
= min_rx
;
567 bfd_profile_update(bp
);
579 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop
581 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args
*args
)
583 return bfd_session_create(args
, false);
586 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args
*args
)
588 return bfd_session_destroy(args
->event
, args
->dnode
, false);
592 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
594 int bfdd_bfd_sessions_single_hop_source_addr_modify(
595 struct nb_cb_modify_args
*args
)
600 int bfdd_bfd_sessions_single_hop_source_addr_destroy(
601 struct nb_cb_destroy_args
*args
)
607 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/profile
609 int bfdd_bfd_sessions_single_hop_profile_modify(struct nb_cb_modify_args
*args
)
611 struct bfd_session
*bs
;
613 if (args
->event
!= NB_EV_APPLY
)
616 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
617 bfd_profile_apply(yang_dnode_get_string(args
->dnode
, NULL
), bs
);
622 int bfdd_bfd_sessions_single_hop_profile_destroy(
623 struct nb_cb_destroy_args
*args
)
625 struct bfd_session
*bs
;
627 if (args
->event
!= NB_EV_APPLY
)
630 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
631 bfd_profile_remove(bs
);
637 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
639 int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
640 struct nb_cb_modify_args
*args
)
642 uint8_t detection_multiplier
= yang_dnode_get_uint8(args
->dnode
, NULL
);
643 struct bfd_session
*bs
;
645 switch (args
->event
) {
654 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
655 bs
->peer_profile
.detection_multiplier
= detection_multiplier
;
656 bfd_session_apply(bs
);
668 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
670 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
671 struct nb_cb_modify_args
*args
)
673 uint32_t tx_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
674 struct bfd_session
*bs
;
676 switch (args
->event
) {
678 if (tx_interval
< 10000 || tx_interval
> 60000000)
679 return NB_ERR_VALIDATION
;
687 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
688 if (tx_interval
== bs
->timers
.desired_min_tx
)
691 bs
->peer_profile
.min_tx
= tx_interval
;
692 bfd_session_apply(bs
);
704 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
706 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
707 struct nb_cb_modify_args
*args
)
709 uint32_t rx_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
710 struct bfd_session
*bs
;
712 switch (args
->event
) {
714 if (rx_interval
< 10000 || rx_interval
> 60000000)
715 return NB_ERR_VALIDATION
;
723 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
724 if (rx_interval
== bs
->timers
.required_min_rx
)
727 bs
->peer_profile
.min_rx
= rx_interval
;
728 bfd_session_apply(bs
);
740 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
742 int bfdd_bfd_sessions_single_hop_administrative_down_modify(
743 struct nb_cb_modify_args
*args
)
745 bool shutdown
= yang_dnode_get_bool(args
->dnode
, NULL
);
746 struct bfd_session
*bs
;
748 switch (args
->event
) {
760 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
761 bs
->peer_profile
.admin_shutdown
= shutdown
;
762 bfd_session_apply(bs
);
768 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode
770 int bfdd_bfd_sessions_single_hop_passive_mode_modify(
771 struct nb_cb_modify_args
*args
)
773 struct bfd_session
*bs
;
776 switch (args
->event
) {
788 passive
= yang_dnode_get_bool(args
->dnode
, NULL
);
790 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
791 bs
->peer_profile
.passive
= passive
;
792 bfd_session_apply(bs
);
798 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
800 int bfdd_bfd_sessions_single_hop_echo_mode_modify(
801 struct nb_cb_modify_args
*args
)
803 bool echo
= yang_dnode_get_bool(args
->dnode
, NULL
);
804 struct bfd_session
*bs
;
806 switch (args
->event
) {
818 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
819 bs
->peer_profile
.echo_mode
= echo
;
820 bfd_session_apply(bs
);
827 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
829 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
830 struct nb_cb_modify_args
*args
)
832 uint32_t echo_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
833 struct bfd_session
*bs
;
835 switch (args
->event
) {
837 if (echo_interval
< 10000 || echo_interval
> 60000000)
838 return NB_ERR_VALIDATION
;
846 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
847 if (echo_interval
== bs
->timers
.desired_min_echo_tx
)
850 bs
->peer_profile
.min_echo_tx
= echo_interval
;
851 bfd_session_apply(bs
);
864 * /frr-bfdd:bfdd/bfd/sessions/single-hop/required-echo-receive-interval
866 int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
867 struct nb_cb_modify_args
*args
)
869 uint32_t echo_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
870 struct bfd_session
*bs
;
872 switch (args
->event
) {
874 if (echo_interval
== 0)
876 if (echo_interval
< 10000 || echo_interval
> 60000000)
877 return NB_ERR_VALIDATION
;
885 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
886 if (echo_interval
== bs
->timers
.required_min_echo_rx
)
889 bs
->peer_profile
.min_echo_rx
= echo_interval
;
890 bfd_session_apply(bs
);
902 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
904 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args
*args
)
906 return bfd_session_create(args
, true);
909 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args
*args
)
911 return bfd_session_destroy(args
->event
, args
->dnode
, true);
915 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl
917 int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
918 struct nb_cb_modify_args
*args
)
920 struct bfd_session
*bs
;
922 switch (args
->event
) {
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
);
941 int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
942 struct nb_cb_destroy_args
*args
)
944 struct bfd_session
*bs
;
946 switch (args
->event
) {
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
);