]>
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 /* Get optional interface and vrf names. */
49 if (yang_dnode_exists(dnode
, "./interface"))
50 ifname
= yang_dnode_get_string(dnode
, "./interface");
51 if (yang_dnode_exists(dnode
, "./vrf"))
52 vrfname
= yang_dnode_get_string(dnode
, "./vrf");
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");
76 * To support old FRR versions we must allow empty
77 * interface to be specified, however that should
78 * change in the future.
80 if (yang_dnode_exists(dnode
, "./interface"))
81 ifname
= yang_dnode_get_string(dnode
, "./interface");
85 if (p
.family
== AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)
86 && strlen(ifname
) == 0) {
88 "%s: when using link-local you must specify "
91 return NB_ERR_VALIDATION
;
96 bfd_session_get_key(mhop
, dnode
, &bk
);
97 bs
= bfd_key_lookup(bk
);
99 /* This session was already configured by another daemon. */
101 /* Now it is configured also by CLI. */
102 BFD_SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
109 bs
= bfd_session_new();
111 return NB_ERR_RESOURCE
;
113 /* Fill the session key. */
114 bfd_session_get_key(mhop
, dnode
, &bs
->key
);
116 /* Set configuration flags. */
118 BFD_SET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
120 BFD_SET_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
);
121 if (bs
->key
.family
== AF_INET6
)
122 BFD_SET_FLAG(bs
->flags
, BFD_SESS_FLAG_IPV6
);
130 /* Only attempt to registrate if freshly allocated. */
131 if (bs
->discrs
.my_discr
== 0 && bs_registrate(bs
) == NULL
)
132 return NB_ERR_RESOURCE
;
134 nb_running_set_entry(dnode
, bs
);
139 if (bs
->refcount
<= 1)
140 bfd_session_free(resource
->ptr
);
147 static int bfd_session_destroy(enum nb_event event
,
148 const struct lyd_node
*dnode
, bool mhop
)
150 struct bfd_session
*bs
;
155 bfd_session_get_key(mhop
, dnode
, &bk
);
156 if (bfd_key_lookup(bk
) == NULL
)
157 return NB_ERR_INCONSISTENCY
;
165 bs
= nb_running_unset_entry(dnode
);
166 /* CLI is not using this session anymore. */
167 if (BFD_CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
) == 0)
170 BFD_UNSET_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
);
172 /* There are still daemons using it. */
173 if (bs
->refcount
> 0)
176 bfd_session_free(bs
);
188 * XPath: /frr-bfdd:bfdd/bfd
190 int bfdd_bfd_create(enum nb_event event
,
191 const struct lyd_node
*dnode
__attribute__((__unused__
)),
192 union nb_resource
*resource
__attribute__((__unused__
)))
198 int bfdd_bfd_destroy(enum nb_event event
, const struct lyd_node
*dnode
)
210 bfd_sessions_remove_manual();
222 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop
224 int bfdd_bfd_sessions_single_hop_create(enum nb_event event
,
225 const struct lyd_node
*dnode
,
226 union nb_resource
*resource
)
228 return bfd_session_create(event
, dnode
, resource
, false);
231 int bfdd_bfd_sessions_single_hop_destroy(enum nb_event event
,
232 const struct lyd_node
*dnode
)
234 return bfd_session_destroy(event
, dnode
, false);
238 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
240 int bfdd_bfd_sessions_single_hop_source_addr_modify(enum nb_event event
241 __attribute__((__unused__
)),
242 const struct lyd_node
*dnode
243 __attribute__((__unused__
)),
244 union nb_resource
*resource
245 __attribute__((__unused__
)))
250 int bfdd_bfd_sessions_single_hop_source_addr_destroy(
251 enum nb_event event
__attribute__((__unused__
)),
252 const struct lyd_node
*dnode
__attribute__((__unused__
)))
258 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
260 int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
261 enum nb_event event
, const struct lyd_node
*dnode
,
262 union nb_resource
*resource
__attribute__((__unused__
)))
264 uint8_t detection_multiplier
= yang_dnode_get_uint8(dnode
, NULL
);
265 struct bfd_session
*bs
;
276 bs
= nb_running_get_entry(dnode
, NULL
, true);
277 bs
->detect_mult
= detection_multiplier
;
289 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
291 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
292 enum nb_event event
, const struct lyd_node
*dnode
,
293 union nb_resource
*resource
__attribute__((__unused__
)))
295 uint32_t tx_interval
= yang_dnode_get_uint32(dnode
, NULL
);
296 struct bfd_session
*bs
;
300 if (tx_interval
< 10000 || tx_interval
> 60000000)
301 return NB_ERR_VALIDATION
;
309 bs
= nb_running_get_entry(dnode
, NULL
, true);
310 if (tx_interval
== bs
->timers
.desired_min_tx
)
313 bs
->timers
.desired_min_tx
= tx_interval
;
326 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
328 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
329 enum nb_event event
, const struct lyd_node
*dnode
,
330 union nb_resource
*resource
__attribute__((__unused__
)))
332 uint32_t rx_interval
= yang_dnode_get_uint32(dnode
, NULL
);
333 struct bfd_session
*bs
;
337 if (rx_interval
< 10000 || rx_interval
> 60000000)
338 return NB_ERR_VALIDATION
;
346 bs
= nb_running_get_entry(dnode
, NULL
, true);
347 if (rx_interval
== bs
->timers
.required_min_rx
)
350 bs
->timers
.required_min_rx
= rx_interval
;
363 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
365 int bfdd_bfd_sessions_single_hop_administrative_down_modify(
366 enum nb_event event
, const struct lyd_node
*dnode
,
367 union nb_resource
*resource
__attribute__((__unused__
)))
369 bool shutdown
= yang_dnode_get_bool(dnode
, NULL
);
370 struct bfd_session
*bs
;
384 bs
= nb_running_get_entry(dnode
, NULL
, true);
386 if (shutdown
== false) {
387 if (!BFD_CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_SHUTDOWN
))
390 BFD_UNSET_FLAG(bs
->flags
, BFD_SESS_FLAG_SHUTDOWN
);
392 /* Change and notify state change. */
393 bs
->ses_state
= PTM_BFD_DOWN
;
394 control_notify(bs
, bs
->ses_state
);
396 /* Enable all timers. */
397 bfd_recvtimer_update(bs
);
398 bfd_xmttimer_update(bs
, bs
->xmt_TO
);
399 if (BFD_CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_ECHO
)) {
400 bfd_echo_recvtimer_update(bs
);
401 bfd_echo_xmttimer_update(bs
, bs
->echo_xmt_TO
);
404 if (BFD_CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_SHUTDOWN
))
407 BFD_SET_FLAG(bs
->flags
, BFD_SESS_FLAG_SHUTDOWN
);
409 /* Disable all events. */
410 bfd_recvtimer_delete(bs
);
411 bfd_echo_recvtimer_delete(bs
);
412 bfd_xmttimer_delete(bs
);
413 bfd_echo_xmttimer_delete(bs
);
415 /* Change and notify state change. */
416 bs
->ses_state
= PTM_BFD_ADM_DOWN
;
417 control_notify(bs
, bs
->ses_state
);
426 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
428 int bfdd_bfd_sessions_single_hop_echo_mode_modify(enum nb_event event
,
429 const struct lyd_node
*dnode
,
430 union nb_resource
*resource
431 __attribute__((__unused__
)))
433 bool echo
= yang_dnode_get_bool(dnode
, NULL
);
434 struct bfd_session
*bs
;
448 bs
= nb_running_get_entry(dnode
, NULL
, true);
451 if (!BFD_CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_ECHO
))
454 BFD_UNSET_FLAG(bs
->flags
, BFD_SESS_FLAG_ECHO
);
455 ptm_bfd_echo_stop(bs
);
457 if (BFD_CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_ECHO
))
460 BFD_SET_FLAG(bs
->flags
, BFD_SESS_FLAG_ECHO
);
461 /* Apply setting immediately. */
462 if (!BFD_CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_SHUTDOWN
))
463 bs_echo_timer_handler(bs
);
471 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
473 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
474 enum nb_event event
, const struct lyd_node
*dnode
,
475 union nb_resource
*resource
__attribute__((__unused__
)))
477 uint32_t echo_interval
= yang_dnode_get_uint32(dnode
, NULL
);
478 struct bfd_session
*bs
;
482 if (echo_interval
< 10000 || echo_interval
> 60000000)
483 return NB_ERR_VALIDATION
;
491 bs
= nb_running_get_entry(dnode
, NULL
, true);
492 if (echo_interval
== bs
->timers
.required_min_echo
)
495 bs
->timers
.required_min_echo
= echo_interval
;
507 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
509 int bfdd_bfd_sessions_multi_hop_create(enum nb_event event
,
510 const struct lyd_node
*dnode
,
511 union nb_resource
*resource
)
513 return bfd_session_create(event
, dnode
, resource
, true);
516 int bfdd_bfd_sessions_multi_hop_destroy(enum nb_event event
,
517 const struct lyd_node
*dnode
)
519 return bfd_session_destroy(event
, dnode
, true);