]>
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
);
58 static int bfd_session_create(enum nb_event event
, const struct lyd_node
*dnode
,
59 union nb_resource
*resource
, bool mhop
)
61 struct bfd_session
*bs
;
69 * When `dest-addr` is IPv6 and link-local we must
70 * require interface name, otherwise we can't figure
71 * which interface to use to send the packets.
73 yang_dnode_get_prefix(&p
, dnode
, "./dest-addr");
75 ifname
= yang_dnode_get_string(dnode
, "./interface");
77 if (p
.family
== AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)
78 && strcmp(ifname
, "*") == 0) {
80 "%s: when using link-local you must specify an interface.",
82 return NB_ERR_VALIDATION
;
87 bfd_session_get_key(mhop
, dnode
, &bk
);
88 bs
= bfd_key_lookup(bk
);
90 /* This session was already configured by another daemon. */
92 /* Now it is configured also by CLI. */
93 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
100 bs
= bfd_session_new();
102 /* Fill the session key. */
103 bfd_session_get_key(mhop
, dnode
, &bs
->key
);
105 /* Set configuration flags. */
107 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
109 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
);
110 if (bs
->key
.family
== AF_INET6
)
111 SET_FLAG(bs
->flags
, BFD_SESS_FLAG_IPV6
);
119 /* Only attempt to registrate if freshly allocated. */
120 if (bs
->discrs
.my_discr
== 0 && bs_registrate(bs
) == NULL
)
121 return NB_ERR_RESOURCE
;
123 nb_running_set_entry(dnode
, bs
);
128 if (bs
->refcount
<= 1)
129 bfd_session_free(resource
->ptr
);
136 static int bfd_session_destroy(enum nb_event event
,
137 const struct lyd_node
*dnode
, bool mhop
)
139 struct bfd_session
*bs
;
144 bfd_session_get_key(mhop
, dnode
, &bk
);
145 if (bfd_key_lookup(bk
) == NULL
)
146 return NB_ERR_INCONSISTENCY
;
154 bs
= nb_running_unset_entry(dnode
);
155 /* CLI is not using this session anymore. */
156 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
) == 0)
159 UNSET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
161 /* There are still daemons using it. */
162 if (bs
->refcount
> 0)
165 bfd_session_free(bs
);
177 * XPath: /frr-bfdd:bfdd/bfd
179 int bfdd_bfd_create(struct nb_cb_create_args
*args
)
185 int bfdd_bfd_destroy(struct nb_cb_destroy_args
*args
)
187 switch (args
->event
) {
197 bfd_sessions_remove_manual();
209 * XPath: /frr-bfdd:bfdd/bfd/profile
211 int bfdd_bfd_profile_create(struct nb_cb_create_args
*args
)
213 struct bfd_profile
*bp
;
216 if (args
->event
!= NB_EV_APPLY
)
219 name
= yang_dnode_get_string(args
->dnode
, "./name");
220 bp
= bfd_profile_new(name
);
221 nb_running_set_entry(args
->dnode
, bp
);
226 int bfdd_bfd_profile_destroy(struct nb_cb_destroy_args
*args
)
228 struct bfd_profile
*bp
;
230 if (args
->event
!= NB_EV_APPLY
)
233 bp
= nb_running_unset_entry(args
->dnode
);
234 bfd_profile_free(bp
);
240 * XPath: /frr-bfdd:bfdd/bfd/profile/detection-multiplier
242 int bfdd_bfd_profile_detection_multiplier_modify(struct nb_cb_modify_args
*args
)
244 struct bfd_profile
*bp
;
246 if (args
->event
!= NB_EV_APPLY
)
249 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
250 bp
->detection_multiplier
= yang_dnode_get_uint8(args
->dnode
, NULL
);
251 bfd_profile_update(bp
);
257 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-transmission-interval
259 int bfdd_bfd_profile_desired_transmission_interval_modify(
260 struct nb_cb_modify_args
*args
)
262 struct bfd_profile
*bp
;
265 switch (args
->event
) {
267 min_tx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
268 if (min_tx
< 10000 || min_tx
> 60000000)
269 return NB_ERR_VALIDATION
;
277 min_tx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
278 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
279 if (bp
->min_tx
== min_tx
)
283 bfd_profile_update(bp
);
295 * XPath: /frr-bfdd:bfdd/bfd/profile/required-receive-interval
297 int bfdd_bfd_profile_required_receive_interval_modify(
298 struct nb_cb_modify_args
*args
)
300 struct bfd_profile
*bp
;
303 switch (args
->event
) {
305 min_rx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
306 if (min_rx
< 10000 || min_rx
> 60000000)
307 return NB_ERR_VALIDATION
;
315 min_rx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
316 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
317 if (bp
->min_rx
== min_rx
)
321 bfd_profile_update(bp
);
333 * XPath: /frr-bfdd:bfdd/bfd/profile/administrative-down
335 int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args
*args
)
337 struct bfd_profile
*bp
;
340 if (args
->event
!= NB_EV_APPLY
)
343 shutdown
= yang_dnode_get_bool(args
->dnode
, NULL
);
344 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
345 if (bp
->admin_shutdown
== shutdown
)
348 bp
->admin_shutdown
= shutdown
;
349 bfd_profile_update(bp
);
355 * XPath: /frr-bfdd:bfdd/bfd/profile/passive-mode
357 int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args
*args
)
359 struct bfd_profile
*bp
;
362 if (args
->event
!= NB_EV_APPLY
)
365 passive
= yang_dnode_get_bool(args
->dnode
, NULL
);
366 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
367 if (bp
->passive
== passive
)
370 bp
->passive
= passive
;
371 bfd_profile_update(bp
);
377 * XPath: /frr-bfdd:bfdd/bfd/profile/minimum-ttl
379 int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args
*args
)
381 struct bfd_profile
*bp
;
384 if (args
->event
!= NB_EV_APPLY
)
387 minimum_ttl
= yang_dnode_get_uint8(args
->dnode
, NULL
);
388 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
389 if (bp
->minimum_ttl
== minimum_ttl
)
392 bp
->minimum_ttl
= minimum_ttl
;
393 bfd_profile_update(bp
);
398 int bfdd_bfd_profile_minimum_ttl_destroy(struct nb_cb_destroy_args
*args
)
400 struct bfd_profile
*bp
;
402 if (args
->event
!= NB_EV_APPLY
)
405 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
406 bp
->minimum_ttl
= BFD_DEF_MHOP_TTL
;
407 bfd_profile_update(bp
);
413 * XPath: /frr-bfdd:bfdd/bfd/profile/echo-mode
415 int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args
*args
)
417 struct bfd_profile
*bp
;
420 if (args
->event
!= NB_EV_APPLY
)
423 echo
= yang_dnode_get_bool(args
->dnode
, NULL
);
424 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
425 if (bp
->echo_mode
== echo
)
428 bp
->echo_mode
= echo
;
429 bfd_profile_update(bp
);
435 * XPath: /frr-bfdd:bfdd/bfd/profile/desired-echo-echo-transmission-interval
437 int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
438 struct nb_cb_modify_args
*args
)
440 struct bfd_profile
*bp
;
443 switch (args
->event
) {
445 min_rx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
446 if (min_rx
< 10000 || min_rx
> 60000000)
447 return NB_ERR_VALIDATION
;
455 min_rx
= yang_dnode_get_uint32(args
->dnode
, NULL
);
456 bp
= nb_running_get_entry(args
->dnode
, NULL
, true);
457 if (bp
->min_echo_rx
== min_rx
)
460 bp
->min_echo_rx
= min_rx
;
461 bfd_profile_update(bp
);
473 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop
475 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args
*args
)
477 return bfd_session_create(args
->event
, args
->dnode
, args
->resource
,
481 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args
*args
)
483 return bfd_session_destroy(args
->event
, args
->dnode
, false);
487 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
489 int bfdd_bfd_sessions_single_hop_source_addr_modify(
490 struct nb_cb_modify_args
*args
)
495 int bfdd_bfd_sessions_single_hop_source_addr_destroy(
496 struct nb_cb_destroy_args
*args
)
502 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/profile
504 int bfdd_bfd_sessions_single_hop_profile_modify(struct nb_cb_modify_args
*args
)
506 struct bfd_session
*bs
;
508 if (args
->event
!= NB_EV_APPLY
)
511 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
512 bfd_profile_apply(yang_dnode_get_string(args
->dnode
, NULL
), bs
);
517 int bfdd_bfd_sessions_single_hop_profile_destroy(
518 struct nb_cb_destroy_args
*args
)
520 struct bfd_session
*bs
;
522 if (args
->event
!= NB_EV_APPLY
)
525 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
526 bfd_profile_remove(bs
);
532 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
534 int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
535 struct nb_cb_modify_args
*args
)
537 uint8_t detection_multiplier
= yang_dnode_get_uint8(args
->dnode
, NULL
);
538 struct bfd_session
*bs
;
540 switch (args
->event
) {
549 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
550 bs
->peer_profile
.detection_multiplier
= detection_multiplier
;
551 bfd_session_apply(bs
);
563 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
565 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
566 struct nb_cb_modify_args
*args
)
568 uint32_t tx_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
569 struct bfd_session
*bs
;
571 switch (args
->event
) {
573 if (tx_interval
< 10000 || tx_interval
> 60000000)
574 return NB_ERR_VALIDATION
;
582 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
583 if (tx_interval
== bs
->timers
.desired_min_tx
)
586 bs
->peer_profile
.min_tx
= tx_interval
;
587 bfd_session_apply(bs
);
599 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
601 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
602 struct nb_cb_modify_args
*args
)
604 uint32_t rx_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
605 struct bfd_session
*bs
;
607 switch (args
->event
) {
609 if (rx_interval
< 10000 || rx_interval
> 60000000)
610 return NB_ERR_VALIDATION
;
618 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
619 if (rx_interval
== bs
->timers
.required_min_rx
)
622 bs
->peer_profile
.min_rx
= rx_interval
;
623 bfd_session_apply(bs
);
635 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
637 int bfdd_bfd_sessions_single_hop_administrative_down_modify(
638 struct nb_cb_modify_args
*args
)
640 bool shutdown
= yang_dnode_get_bool(args
->dnode
, NULL
);
641 struct bfd_session
*bs
;
643 switch (args
->event
) {
655 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
656 bs
->peer_profile
.admin_shutdown
= shutdown
;
657 bfd_session_apply(bs
);
663 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode
665 int bfdd_bfd_sessions_single_hop_passive_mode_modify(
666 struct nb_cb_modify_args
*args
)
668 struct bfd_session
*bs
;
671 switch (args
->event
) {
683 passive
= yang_dnode_get_bool(args
->dnode
, NULL
);
685 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
686 bs
->peer_profile
.passive
= passive
;
687 bfd_session_apply(bs
);
693 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
695 int bfdd_bfd_sessions_single_hop_echo_mode_modify(
696 struct nb_cb_modify_args
*args
)
698 bool echo
= yang_dnode_get_bool(args
->dnode
, NULL
);
699 struct bfd_session
*bs
;
701 switch (args
->event
) {
713 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
714 bs
->peer_profile
.echo_mode
= echo
;
715 bfd_session_apply(bs
);
722 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
724 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
725 struct nb_cb_modify_args
*args
)
727 uint32_t echo_interval
= yang_dnode_get_uint32(args
->dnode
, NULL
);
728 struct bfd_session
*bs
;
730 switch (args
->event
) {
732 if (echo_interval
< 10000 || echo_interval
> 60000000)
733 return NB_ERR_VALIDATION
;
741 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
742 if (echo_interval
== bs
->timers
.required_min_echo
)
745 bs
->peer_profile
.min_echo_rx
= echo_interval
;
746 bfd_session_apply(bs
);
758 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
760 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args
*args
)
762 return bfd_session_create(args
->event
, args
->dnode
, args
->resource
,
766 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args
*args
)
768 return bfd_session_destroy(args
->event
, args
->dnode
, true);
772 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl
774 int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
775 struct nb_cb_modify_args
*args
)
777 struct bfd_session
*bs
;
779 switch (args
->event
) {
791 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
792 bs
->peer_profile
.minimum_ttl
= yang_dnode_get_uint8(args
->dnode
, NULL
);
793 bfd_session_apply(bs
);
798 int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
799 struct nb_cb_destroy_args
*args
)
801 struct bfd_session
*bs
;
803 switch (args
->event
) {
815 bs
= nb_running_get_entry(args
->dnode
, NULL
, true);
816 bs
->peer_profile
.minimum_ttl
= BFD_DEF_MHOP_TTL
;
817 bfd_session_apply(bs
);