+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* BFD daemon northbound implementation.
*
* Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
* Rafael Zalamena
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
*/
#include <zebra.h>
if (yang_dnode_exists(dnode, "./source-addr"))
strtosa(yang_dnode_get_string(dnode, "./source-addr"), &lsa);
- ifname = yang_dnode_get_string(dnode, "./interface");
vrfname = yang_dnode_get_string(dnode, "./vrf");
- if (strcmp(ifname, "*") == 0)
- ifname = NULL;
+ if (!mhop) {
+ ifname = yang_dnode_get_string(dnode, "./interface");
+ if (strcmp(ifname, "*") == 0)
+ ifname = NULL;
+ }
/* Generate the corresponding key. */
gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname);
const struct lyd_node *sess_dnode;
struct session_iter iter;
struct bfd_session *bs;
- const char *source;
const char *dest;
const char *ifname;
const char *vrfname;
switch (args->event) {
case NB_EV_VALIDATE:
+ yang_dnode_get_prefix(&p, args->dnode, "./dest-addr");
+
+ if (mhop) {
+ /*
+ * Do not allow IPv6 link-local address for multihop.
+ */
+ if (p.family == AF_INET6
+ && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
+ snprintf(
+ args->errmsg, args->errmsg_len,
+ "Cannot use link-local address for multihop sessions");
+ return NB_ERR_VALIDATION;
+ }
+ return NB_OK;
+ }
+
/*
* When `dest-addr` is IPv6 and link-local we must
* require interface name, otherwise we can't figure
* which interface to use to send the packets.
*/
- yang_dnode_get_prefix(&p, args->dnode, "./dest-addr");
-
ifname = yang_dnode_get_string(args->dnode, "./interface");
if (p.family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)
dest = yang_dnode_get_string(args->dnode, "./dest-addr");
vrfname = yang_dnode_get_string(args->dnode, "./vrf");
- if (mhop) {
- source = yang_dnode_get_string(args->dnode, "./source-addr");
-
- yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
- "./multi-hop[source-addr='%s'][dest-addr='%s'][vrf='%s']",
- source, dest, vrfname);
- } else {
- yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
- "./single-hop[dest-addr='%s'][vrf='%s']",
- dest, vrfname);
- }
+ yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
+ "./single-hop[dest-addr='%s'][vrf='%s']",
+ dest, vrfname);
if (iter.wildcard && iter.count > 1) {
snprintf(
struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint32_t min_tx;
switch (args->event) {
case NB_EV_VALIDATE:
- min_tx = yang_dnode_get_uint32(args->dnode, NULL);
- if (min_tx < 10000 || min_tx > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
break;
case NB_EV_APPLY:
- min_tx = yang_dnode_get_uint32(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->min_tx == min_tx)
- return NB_OK;
-
- bp->min_tx = min_tx;
+ bp->min_tx = yang_dnode_get_uint32(args->dnode, NULL);
bfd_profile_update(bp);
break;
struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint32_t min_rx;
switch (args->event) {
case NB_EV_VALIDATE:
- min_rx = yang_dnode_get_uint32(args->dnode, NULL);
- if (min_rx < 10000 || min_rx > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
break;
case NB_EV_APPLY:
- min_rx = yang_dnode_get_uint32(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->min_rx == min_rx)
- return NB_OK;
-
- bp->min_rx = min_rx;
+ bp->min_rx = yang_dnode_get_uint32(args->dnode, NULL);
bfd_profile_update(bp);
break;
int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- bool shutdown;
if (args->event != NB_EV_APPLY)
return NB_OK;
- shutdown = yang_dnode_get_bool(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->admin_shutdown == shutdown)
- return NB_OK;
-
- bp->admin_shutdown = shutdown;
+ bp->admin_shutdown = yang_dnode_get_bool(args->dnode, NULL);
bfd_profile_update(bp);
return NB_OK;
int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- bool passive;
if (args->event != NB_EV_APPLY)
return NB_OK;
- passive = yang_dnode_get_bool(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->passive == passive)
- return NB_OK;
-
- bp->passive = passive;
+ bp->passive = yang_dnode_get_bool(args->dnode, NULL);
bfd_profile_update(bp);
return NB_OK;
int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint8_t minimum_ttl;
if (args->event != NB_EV_APPLY)
return NB_OK;
- minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->minimum_ttl == minimum_ttl)
- return NB_OK;
-
- bp->minimum_ttl = minimum_ttl;
+ bp->minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
bfd_profile_update(bp);
return NB_OK;
struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint32_t min_tx;
switch (args->event) {
case NB_EV_VALIDATE:
- min_tx = yang_dnode_get_uint32(args->dnode, NULL);
- if (min_tx < 10000 || min_tx > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
break;
case NB_EV_APPLY:
- min_tx = yang_dnode_get_uint32(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->min_echo_tx == min_tx)
- return NB_OK;
-
- bp->min_echo_tx = min_tx;
+ bp->min_echo_tx = yang_dnode_get_uint32(args->dnode, NULL);
bfd_profile_update(bp);
break;
struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
- uint32_t min_rx;
switch (args->event) {
case NB_EV_VALIDATE:
- min_rx = yang_dnode_get_uint32(args->dnode, NULL);
- if (min_rx == 0)
- return NB_OK;
- if (min_rx < 10000 || min_rx > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
break;
case NB_EV_APPLY:
- min_rx = yang_dnode_get_uint32(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
- if (bp->min_echo_rx == min_rx)
- return NB_OK;
-
- bp->min_echo_rx = min_rx;
+ bp->min_echo_rx = yang_dnode_get_uint32(args->dnode, NULL);
bfd_profile_update(bp);
break;
int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
struct nb_cb_modify_args *args)
{
- uint32_t tx_interval = yang_dnode_get_uint32(args->dnode, NULL);
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
- if (tx_interval < 10000 || tx_interval > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
case NB_EV_APPLY:
bs = nb_running_get_entry(args->dnode, NULL, true);
- if (tx_interval == bs->timers.desired_min_tx)
- return NB_OK;
-
- bs->peer_profile.min_tx = tx_interval;
+ bs->peer_profile.min_tx =
+ yang_dnode_get_uint32(args->dnode, NULL);
bfd_session_apply(bs);
break;
int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
struct nb_cb_modify_args *args)
{
- uint32_t rx_interval = yang_dnode_get_uint32(args->dnode, NULL);
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
- if (rx_interval < 10000 || rx_interval > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
case NB_EV_APPLY:
bs = nb_running_get_entry(args->dnode, NULL, true);
- if (rx_interval == bs->timers.required_min_rx)
- return NB_OK;
-
- bs->peer_profile.min_rx = rx_interval;
+ bs->peer_profile.min_rx =
+ yang_dnode_get_uint32(args->dnode, NULL);
bfd_session_apply(bs);
break;
int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
struct nb_cb_modify_args *args)
{
- uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
- if (echo_interval < 10000 || echo_interval > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
case NB_EV_APPLY:
bs = nb_running_get_entry(args->dnode, NULL, true);
- if (echo_interval == bs->timers.desired_min_echo_tx)
- return NB_OK;
-
- bs->peer_profile.min_echo_tx = echo_interval;
+ bs->peer_profile.min_echo_tx =
+ yang_dnode_get_uint32(args->dnode, NULL);
bfd_session_apply(bs);
break;
int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
struct nb_cb_modify_args *args)
{
- uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
- if (echo_interval == 0)
- return NB_OK;
- if (echo_interval < 10000 || echo_interval > 60000000)
- return NB_ERR_VALIDATION;
break;
case NB_EV_PREPARE:
case NB_EV_APPLY:
bs = nb_running_get_entry(args->dnode, NULL, true);
- if (echo_interval == bs->timers.required_min_echo_rx)
- return NB_OK;
-
- bs->peer_profile.min_echo_rx = echo_interval;
+ bs->peer_profile.min_echo_rx =
+ yang_dnode_get_uint32(args->dnode, NULL);
bfd_session_apply(bs);
break;