bfdd: migrate session commands to northbound

Lets start using the new BFD yang model and translate the BFD session
configuration commands to use the northbound.

One important change: all sessions will default to use
`VRF_DEFAULT_NAME` (usually "default") when no VRF is configured. All
places which search for BFD sessions must now take this into account.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
Rafael Zalamena 2019-05-23 16:09:24 -03:00
parent 3e4e7405ff
commit adc26455bf
8 changed files with 1397 additions and 279 deletions

View file

@ -34,7 +34,6 @@
DEFINE_MTYPE_STATIC(BFDD, BFDD_CONFIG, "long-lived configuration memory") DEFINE_MTYPE_STATIC(BFDD, BFDD_CONFIG, "long-lived configuration memory")
DEFINE_MTYPE_STATIC(BFDD, BFDD_SESSION_OBSERVER, "Session observer") DEFINE_MTYPE_STATIC(BFDD, BFDD_SESSION_OBSERVER, "Session observer")
DEFINE_MTYPE_STATIC(BFDD, BFDD_VRF, "BFD VRF") DEFINE_MTYPE_STATIC(BFDD, BFDD_VRF, "BFD VRF")
DEFINE_QOBJ_TYPE(bfd_session)
/* /*
* Prototypes * Prototypes
@ -85,6 +84,8 @@ void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
strlcpy(key->ifname, ifname, sizeof(key->ifname)); strlcpy(key->ifname, ifname, sizeof(key->ifname));
if (vrfname && vrfname[0]) if (vrfname && vrfname[0])
strlcpy(key->vrfname, vrfname, sizeof(key->vrfname)); strlcpy(key->vrfname, vrfname, sizeof(key->vrfname));
else
strlcpy(key->vrfname, VRF_DEFAULT_NAME, sizeof(key->vrfname));
} }
struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc) struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
@ -390,17 +391,13 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,
/* Search for session without using discriminator. */ /* Search for session without using discriminator. */
ifp = if_lookup_by_index(ifindex, vrfid); ifp = if_lookup_by_index(ifindex, vrfid);
if (vrfid == VRF_DEFAULT) { if (vrfid != VRF_DEFAULT)
/*
* Don't use the default vrf, otherwise we won't find
* sessions that doesn't specify it.
*/
vrf = NULL;
} else
vrf = vrf_lookup_by_id(vrfid); vrf = vrf_lookup_by_id(vrfid);
else
vrf = NULL;
gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL, gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL,
vrf ? vrf->name : NULL); vrf ? vrf->name : VRF_DEFAULT_NAME);
/* XXX maybe remoteDiscr should be checked for remoteHeard cases. */ /* XXX maybe remoteDiscr should be checked for remoteHeard cases. */
return bfd_key_lookup(key); return bfd_key_lookup(key);
@ -469,8 +466,6 @@ struct bfd_session *bfd_session_new(void)
bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(*bs)); bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(*bs));
QOBJ_REG(bs, bfd_session);
bs->timers.desired_min_tx = BFD_DEFDESIREDMINTX; bs->timers.desired_min_tx = BFD_DEFDESIREDMINTX;
bs->timers.required_min_rx = BFD_DEFREQUIREDMINRX; bs->timers.required_min_rx = BFD_DEFREQUIREDMINRX;
bs->timers.required_min_echo = BFD_DEF_REQ_MIN_ECHO; bs->timers.required_min_echo = BFD_DEF_REQ_MIN_ECHO;
@ -644,7 +639,6 @@ void bfd_session_free(struct bfd_session *bs)
pl_free(bs->pl); pl_free(bs->pl);
QOBJ_UNREG(bs);
XFREE(MTYPE_BFDD_CONFIG, bs); XFREE(MTYPE_BFDD_CONFIG, bs);
} }
@ -680,6 +674,9 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
if (bpc->bpc_has_vrfname) if (bpc->bpc_has_vrfname)
strlcpy(bfd->key.vrfname, bpc->bpc_vrfname, strlcpy(bfd->key.vrfname, bpc->bpc_vrfname,
sizeof(bfd->key.vrfname)); sizeof(bfd->key.vrfname));
else
strlcpy(bfd->key.vrfname, VRF_DEFAULT_NAME,
sizeof(bfd->key.vrfname));
/* Copy remaining data. */ /* Copy remaining data. */
if (bpc->bpc_ipv4 == false) if (bpc->bpc_ipv4 == false)
@ -1292,6 +1289,7 @@ static unsigned int bfd_key_hash_do(const void *p);
static void _bfd_free(struct hash_bucket *hb, static void _bfd_free(struct hash_bucket *hb,
void *arg __attribute__((__unused__))); void *arg __attribute__((__unused__)));
int _bfd_session_next(struct hash_bucket *hb, void *arg);
/* BFD hash for our discriminator. */ /* BFD hash for our discriminator. */
static unsigned int bfd_id_hash_do(const void *p) static unsigned int bfd_id_hash_do(const void *p)
@ -1533,6 +1531,62 @@ void bfd_shutdown(void)
hash_free(bfd_key_hash); hash_free(bfd_key_hash);
} }
struct bfd_session_iterator {
int bsi_stop;
bool bsi_mhop;
const struct bfd_session *bsi_bs;
};
int _bfd_session_next(struct hash_bucket *hb, void *arg)
{
struct bfd_session_iterator *bsi = arg;
struct bfd_session *bs = hb->data;
/* Previous entry signaled stop. */
if (bsi->bsi_stop == 1) {
/* Match the single/multi hop sessions. */
if (bs->key.mhop != bsi->bsi_mhop)
return HASHWALK_CONTINUE;
bsi->bsi_bs = bs;
return HASHWALK_ABORT;
}
/* We found the current item, stop in the next one. */
if (bsi->bsi_bs == hb->data) {
bsi->bsi_stop = 1;
/* Set entry to NULL to signal end of list. */
bsi->bsi_bs = NULL;
} else if (bsi->bsi_bs == NULL && bsi->bsi_mhop == bs->key.mhop) {
/* We want the first list item. */
bsi->bsi_stop = 1;
bsi->bsi_bs = hb->data;
return HASHWALK_ABORT;
}
return HASHWALK_CONTINUE;
}
/*
* bfd_session_next: uses the current session to find the next.
*
* `bs` might point to NULL to get the first item of the data structure.
*/
const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
bool mhop)
{
struct bfd_session_iterator bsi;
bsi.bsi_stop = 0;
bsi.bsi_bs = bs;
bsi.bsi_mhop = mhop;
hash_walk(bfd_key_hash, _bfd_session_next, &bsi);
if (bsi.bsi_stop == 0)
return NULL;
return bsi.bsi_bs;
}
/* /*
* VRF related functions. * VRF related functions.
*/ */

View file

@ -252,11 +252,7 @@ struct bfd_session {
struct bfd_timers remote_timers; struct bfd_timers remote_timers;
uint64_t refcount; /* number of pointers referencing this. */ uint64_t refcount; /* number of pointers referencing this. */
/* VTY context data. */
QOBJ_FIELDS
}; };
DECLARE_QOBJ_TYPE(bfd_session)
struct peer_label { struct peer_label {
TAILQ_ENTRY(peer_label) pl_entry; TAILQ_ENTRY(peer_label) pl_entry;
@ -552,6 +548,9 @@ void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
struct bfd_session *bfd_session_new(void); struct bfd_session *bfd_session_new(void);
struct bfd_session *bs_registrate(struct bfd_session *bs); struct bfd_session *bs_registrate(struct bfd_session *bs);
void bfd_session_free(struct bfd_session *bs); void bfd_session_free(struct bfd_session *bs);
const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
bool mhop);
/* BFD hash data structures interface */ /* BFD hash data structures interface */
void bfd_initialize(void); void bfd_initialize(void);
void bfd_shutdown(void); void bfd_shutdown(void);
@ -590,6 +589,14 @@ extern struct in6_addr zero_addr;
void bfdd_vty_init(void); void bfdd_vty_init(void);
/*
* bfdd_cli.c
*
* BFD daemon CLI implementation.
*/
void bfdd_cli_init(void);
/* /*
* ptm_adapter.c * ptm_adapter.c
*/ */
@ -602,4 +609,12 @@ void bfdd_sessions_disable_vrf(struct vrf *vrf);
int ptm_bfd_notify(struct bfd_session *bs); int ptm_bfd_notify(struct bfd_session *bs);
/*
* bfdd_northbound.c
*
* BFD northbound callbacks.
*/
extern const struct frr_yang_module_info frr_bfdd_info;
#endif /* _BFD_H_ */ #endif /* _BFD_H_ */

View file

@ -93,10 +93,17 @@ static struct quagga_signal_t bfd_signals[] = {
}, },
}; };
static const struct frr_yang_module_info *bfdd_yang_modules[] = {
&frr_interface_info,
&frr_bfdd_info,
};
FRR_DAEMON_INFO(bfdd, BFD, .vty_port = 2617, FRR_DAEMON_INFO(bfdd, BFD, .vty_port = 2617,
.proghelp = "Implementation of the BFD protocol.", .proghelp = "Implementation of the BFD protocol.",
.signals = bfd_signals, .n_signals = array_size(bfd_signals), .signals = bfd_signals, .n_signals = array_size(bfd_signals),
.privs = &bglobal.bfdd_privs) .privs = &bglobal.bfdd_privs,
.yang_modules = bfdd_yang_modules,
.n_yang_modules = array_size(bfdd_yang_modules))
#define OPTION_CTLSOCK 1001 #define OPTION_CTLSOCK 1001
static struct option longopts[] = { static struct option longopts[] = {

232
bfdd/bfdd_cli.c Normal file
View file

@ -0,0 +1,232 @@
/*
* BFD daemon CLI 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 "lib/command.h"
#include "lib/log.h"
#include "lib/northbound_cli.h"
#ifndef VTYSH_EXTRACT_PL
#include "bfdd/bfdd_cli_clippy.c"
#endif /* VTYSH_EXTRACT_PL */
#include "bfd.h"
/*
* Definitions.
*/
#define PEER_STR "Configure peer\n"
#define INTERFACE_NAME_STR "Configure interface name to use\n"
#define PEER_IPV4_STR "IPv4 peer address\n"
#define PEER_IPV6_STR "IPv6 peer address\n"
#define MHOP_STR "Configure multihop\n"
#define LOCAL_STR "Configure local address\n"
#define LOCAL_IPV4_STR "IPv4 local address\n"
#define LOCAL_IPV6_STR "IPv6 local address\n"
#define LOCAL_INTF_STR "Configure local interface name to use\n"
#define VRF_STR "Configure VRF\n"
#define VRF_NAME_STR "Configure VRF name\n"
/*
* Prototypes.
*/
/*
* Functions.
*/
DEFPY_NOSH(
bfd_peer_enter, bfd_peer_enter_cmd,
"peer <A.B.C.D|X:X::X:X> [{multihop$multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME$ifname|vrf NAME}]",
PEER_STR
PEER_IPV4_STR
PEER_IPV6_STR
MHOP_STR
LOCAL_STR
LOCAL_IPV4_STR
LOCAL_IPV6_STR
INTERFACE_STR
LOCAL_INTF_STR
VRF_STR
VRF_NAME_STR)
{
int ret, slen;
char xpath[XPATH_MAXLEN];
char source_str[INET6_ADDRSTRLEN];
if (multihop)
snprintf(source_str, sizeof(source_str), "[source-addr='%s']",
local_address_str);
else
source_str[0] = 0;
slen = snprintf(xpath, sizeof(xpath),
"/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
multihop ? "multi-hop" : "single-hop", source_str,
peer_str);
if (ifname)
slen += snprintf(xpath + slen, sizeof(xpath) - slen,
"[interface='%s']", ifname);
else
slen += snprintf(xpath + slen, sizeof(xpath) - slen,
"[interface='']");
if (vrf)
snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']", vrf);
else
snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']",
VRF_DEFAULT_NAME);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
/* Apply settings immediatly. */
ret = nb_cli_apply_changes(vty, NULL);
if (ret == CMD_SUCCESS)
VTY_PUSH_XPATH(BFD_PEER_NODE, xpath);
return ret;
}
DEFPY(
bfd_no_peer, bfd_no_peer_cmd,
"no peer <A.B.C.D|X:X::X:X> [{multihop$multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME$ifname|vrf NAME}]",
NO_STR
PEER_STR
PEER_IPV4_STR
PEER_IPV6_STR
MHOP_STR
LOCAL_STR
LOCAL_IPV4_STR
LOCAL_IPV6_STR
INTERFACE_STR
LOCAL_INTF_STR
VRF_STR
VRF_NAME_STR)
{
int slen;
char xpath[XPATH_MAXLEN];
char source_str[INET6_ADDRSTRLEN];
if (multihop)
snprintf(source_str, sizeof(source_str), "[source-addr='%s']",
local_address_str);
else
source_str[0] = 0;
slen = snprintf(xpath, sizeof(xpath),
"/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
multihop ? "multi-hop" : "single-hop", source_str,
peer_str);
if (ifname)
slen += snprintf(xpath + slen, sizeof(xpath) - slen,
"[interface='%s']", ifname);
else
slen += snprintf(xpath + slen, sizeof(xpath) - slen,
"[interface='']");
if (vrf)
snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']", vrf);
else
snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']",
VRF_DEFAULT_NAME);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
/* Apply settings immediatly. */
return nb_cli_apply_changes(vty, NULL);
}
DEFPY(
bfd_peer_shutdown, bfd_peer_shutdown_cmd,
"[no] shutdown",
NO_STR
"Disable BFD peer")
{
nb_cli_enqueue_change(vty, "./administrative-down", NB_OP_MODIFY,
no ? "false" : "true");
return nb_cli_apply_changes(vty, NULL);
}
DEFPY(
bfd_peer_mult, bfd_peer_mult_cmd,
"detect-multiplier (2-255)$multiplier",
"Configure peer detection multiplier\n"
"Configure peer detection multiplier value\n")
{
nb_cli_enqueue_change(vty, "./detection-multiplier", NB_OP_MODIFY,
multiplier_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY(
bfd_peer_rx, bfd_peer_rx_cmd,
"receive-interval (10-60000)$interval",
"Configure peer receive interval\n"
"Configure peer receive interval value in milliseconds\n")
{
nb_cli_enqueue_change(vty, "./required-receive-interval", NB_OP_MODIFY,
interval_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY(
bfd_peer_tx, bfd_peer_tx_cmd,
"transmit-interval (10-60000)$interval",
"Configure peer transmit interval\n"
"Configure peer transmit interval value in milliseconds\n")
{
nb_cli_enqueue_change(vty, "./desired-transmission-interval",
NB_OP_MODIFY, interval_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY(
bfd_peer_echo, bfd_peer_echo_cmd,
"[no] echo-mode",
NO_STR
"Configure echo mode\n")
{
nb_cli_enqueue_change(vty, "./echo-mode", NB_OP_MODIFY,
no ? "false" : "true");
return nb_cli_apply_changes(vty, NULL);
}
DEFPY(
bfd_peer_echo_interval, bfd_peer_echo_interval_cmd,
"echo-interval (10-60000)$interval",
"Configure peer echo interval\n"
"Configure peer echo interval value in milliseconds\n")
{
nb_cli_enqueue_change(vty, "./desired-echo-transmission-interval",
NB_OP_MODIFY, interval_str);
return nb_cli_apply_changes(vty, NULL);
}
void
bfdd_cli_init(void)
{
install_element(BFD_NODE, &bfd_peer_enter_cmd);
install_element(BFD_NODE, &bfd_no_peer_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_shutdown_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_mult_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_rx_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_tx_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_echo_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_echo_interval_cmd);
}

1060
bfdd/bfdd_northbound.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -34,8 +34,6 @@
/* /*
* Commands help string definitions. * Commands help string definitions.
*/ */
#define PEER_STR "Configure peer\n"
#define INTERFACE_NAME_STR "Configure interface name to use\n"
#define PEER_IPV4_STR "IPv4 peer address\n" #define PEER_IPV4_STR "IPv4 peer address\n"
#define PEER_IPV6_STR "IPv6 peer address\n" #define PEER_IPV6_STR "IPv6 peer address\n"
#define MHOP_STR "Configure multihop\n" #define MHOP_STR "Configure multihop\n"
@ -43,8 +41,6 @@
#define LOCAL_IPV4_STR "IPv4 local address\n" #define LOCAL_IPV4_STR "IPv4 local address\n"
#define LOCAL_IPV6_STR "IPv6 local address\n" #define LOCAL_IPV6_STR "IPv6 local address\n"
#define LOCAL_INTF_STR "Configure local interface name to use\n" #define LOCAL_INTF_STR "Configure local interface name to use\n"
#define VRF_STR "Configure VRF\n"
#define VRF_NAME_STR "Configure VRF name\n"
/* /*
* Prototypes * Prototypes
@ -88,256 +84,6 @@ DEFUN_NOSH(bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n")
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN_NOSH(
bfd_peer_enter, bfd_peer_enter_cmd,
"peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
PEER_STR PEER_IPV4_STR PEER_IPV6_STR
MHOP_STR
LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR
INTERFACE_STR
LOCAL_INTF_STR
VRF_STR VRF_NAME_STR)
{
bool mhop;
int idx;
struct bfd_session *bs;
const char *peer, *ifname, *local, *vrfname;
struct bfd_peer_cfg bpc;
struct sockaddr_any psa, lsa, *lsap;
char errormsg[128];
vrfname = peer = ifname = local = NULL;
/* Gather all provided information. */
peer = argv[1]->arg;
idx = 0;
mhop = argv_find(argv, argc, "multihop", &idx);
idx = 0;
if (argv_find(argv, argc, "interface", &idx))
ifname = argv[idx + 1]->arg;
idx = 0;
if (argv_find(argv, argc, "local-address", &idx))
local = argv[idx + 1]->arg;
idx = 0;
if (argv_find(argv, argc, "vrf", &idx))
vrfname = argv[idx + 1]->arg;
strtosa(peer, &psa);
if (local) {
strtosa(local, &lsa);
lsap = &lsa;
} else
lsap = NULL;
if (bfd_configure_peer(&bpc, mhop, &psa, lsap, ifname, vrfname,
errormsg, sizeof(errormsg))
!= 0) {
vty_out(vty, "%% Invalid peer configuration: %s\n", errormsg);
return CMD_WARNING_CONFIG_FAILED;
}
bs = bs_peer_find(&bpc);
if (bs == NULL) {
bs = ptm_bfd_sess_new(&bpc);
if (bs == NULL) {
vty_out(vty, "%% Failed to add peer.\n");
return CMD_WARNING_CONFIG_FAILED;
}
}
if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) {
if (bs->refcount)
vty_out(vty, "%% session peer is now configurable via bfd daemon.\n");
BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
}
VTY_PUSH_CONTEXT(BFD_PEER_NODE, bs);
return CMD_SUCCESS;
}
DEFPY(bfd_peer_detectmultiplier, bfd_peer_detectmultiplier_cmd,
"detect-multiplier (2-255)$multiplier",
"Configure peer detection multiplier\n"
"Configure peer detection multiplier value\n")
{
struct bfd_session *bs;
bs = VTY_GET_CONTEXT(bfd_session);
if (bs->detect_mult == multiplier)
return CMD_SUCCESS;
bs->detect_mult = multiplier;
return CMD_SUCCESS;
}
DEFPY(bfd_peer_recvinterval, bfd_peer_recvinterval_cmd,
"receive-interval (10-60000)$interval",
"Configure peer receive interval\n"
"Configure peer receive interval value in milliseconds\n")
{
struct bfd_session *bs;
bs = VTY_GET_CONTEXT(bfd_session);
if (bs->timers.required_min_rx == (uint32_t)(interval * 1000))
return CMD_SUCCESS;
bs->timers.required_min_rx = interval * 1000;
bfd_set_polling(bs);
return CMD_SUCCESS;
}
DEFPY(bfd_peer_txinterval, bfd_peer_txinterval_cmd,
"transmit-interval (10-60000)$interval",
"Configure peer transmit interval\n"
"Configure peer transmit interval value in milliseconds\n")
{
struct bfd_session *bs;
bs = VTY_GET_CONTEXT(bfd_session);
if (bs->timers.desired_min_tx == (uint32_t)(interval * 1000))
return CMD_SUCCESS;
bs->timers.desired_min_tx = interval * 1000;
bfd_set_polling(bs);
return CMD_SUCCESS;
}
DEFPY(bfd_peer_echointerval, bfd_peer_echointerval_cmd,
"echo-interval (10-60000)$interval",
"Configure peer echo interval\n"
"Configure peer echo interval value in milliseconds\n")
{
struct bfd_session *bs;
bs = VTY_GET_CONTEXT(bfd_session);
if (bs->timers.required_min_echo == (uint32_t)(interval * 1000))
return CMD_SUCCESS;
bs->timers.required_min_echo = interval * 1000;
return CMD_SUCCESS;
}
DEFPY(bfd_peer_shutdown, bfd_peer_shutdown_cmd, "[no] shutdown",
NO_STR "Disable BFD peer")
{
struct bfd_session *bs;
bs = VTY_GET_CONTEXT(bfd_session);
if (no) {
if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
return CMD_SUCCESS;
BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN);
/* Change and notify state change. */
bs->ses_state = PTM_BFD_DOWN;
control_notify(bs);
/* Enable all timers. */
bfd_recvtimer_update(bs);
bfd_xmttimer_update(bs, bs->xmt_TO);
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) {
bfd_echo_recvtimer_update(bs);
bfd_echo_xmttimer_update(bs, bs->echo_xmt_TO);
}
} else {
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
return CMD_SUCCESS;
BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN);
/* Disable all events. */
bfd_recvtimer_delete(bs);
bfd_echo_recvtimer_delete(bs);
bfd_xmttimer_delete(bs);
bfd_echo_xmttimer_delete(bs);
/* Change and notify state change. */
bs->ses_state = PTM_BFD_ADM_DOWN;
control_notify(bs);
ptm_bfd_snd(bs, 0);
}
return CMD_SUCCESS;
}
DEFPY(bfd_peer_echo, bfd_peer_echo_cmd, "[no] echo-mode",
NO_STR "Configure echo mode\n")
{
struct bfd_session *bs;
bs = VTY_GET_CONTEXT(bfd_session);
if (no) {
if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
return CMD_SUCCESS;
BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO);
ptm_bfd_echo_stop(bs);
} else {
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
return CMD_SUCCESS;
BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO);
/* Apply setting immediately. */
if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
bs_echo_timer_handler(bs);
}
return CMD_SUCCESS;
}
DEFPY(bfd_no_peer, bfd_no_peer_cmd,
"no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]",
NO_STR
PEER_STR PEER_IPV4_STR PEER_IPV6_STR
MHOP_STR
LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR
INTERFACE_STR
LOCAL_INTF_STR
VRF_STR VRF_NAME_STR)
{
int idx;
bool mhop;
struct bfd_peer_cfg bpc;
struct sockaddr_any psa, lsa, *lsap;
char errormsg[128];
strtosa(peer_str, &psa);
if (local) {
strtosa(local_str, &lsa);
lsap = &lsa;
} else {
lsap = NULL;
}
idx = 0;
mhop = argv_find(argv, argc, "multihop", &idx);
if (bfd_configure_peer(&bpc, mhop, &psa, lsap, ifname, vrfname,
errormsg, sizeof(errormsg))
!= 0) {
vty_out(vty, "%% Invalid peer configuration: %s\n", errormsg);
return CMD_WARNING_CONFIG_FAILED;
}
if (ptm_bfd_sess_del(&bpc) != 0) {
vty_out(vty, "%% Failed to remove peer.\n");
return CMD_WARNING_CONFIG_FAILED;
}
return CMD_SUCCESS;
}
/* /*
* Show commands helper functions * Show commands helper functions
@ -1070,16 +816,10 @@ void bfdd_vty_init(void)
/* Install BFD node and commands. */ /* Install BFD node and commands. */
install_node(&bfd_node, bfdd_write_config); install_node(&bfd_node, bfdd_write_config);
install_default(BFD_NODE); install_default(BFD_NODE);
install_element(BFD_NODE, &bfd_peer_enter_cmd);
install_element(BFD_NODE, &bfd_no_peer_cmd);
/* Install BFD peer node. */ /* Install BFD peer node. */
install_node(&bfd_peer_node, bfdd_peer_write_config); install_node(&bfd_peer_node, bfdd_peer_write_config);
install_default(BFD_PEER_NODE); install_default(BFD_PEER_NODE);
install_element(BFD_PEER_NODE, &bfd_peer_detectmultiplier_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_recvinterval_cmd); bfdd_cli_init();
install_element(BFD_PEER_NODE, &bfd_peer_txinterval_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_echointerval_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_shutdown_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_echo_cmd);
} }

View file

@ -7,12 +7,15 @@ noinst_LIBRARIES += bfdd/libbfd.a
sbin_PROGRAMS += bfdd/bfdd sbin_PROGRAMS += bfdd/bfdd
dist_examples_DATA += bfdd/bfdd.conf.sample dist_examples_DATA += bfdd/bfdd.conf.sample
vtysh_scan += $(top_srcdir)/bfdd/bfdd_vty.c vtysh_scan += $(top_srcdir)/bfdd/bfdd_vty.c
vtysh_scan += $(top_srcdir)/bfdd/bfdd_cli.c
man8 += $(MANBUILD)/bfdd.8 man8 += $(MANBUILD)/bfdd.8
endif endif
bfdd_libbfd_a_SOURCES = \ bfdd_libbfd_a_SOURCES = \
bfdd/bfd.c \ bfdd/bfd.c \
bfdd/bfdd_northbound.c \
bfdd/bfdd_vty.c \ bfdd/bfdd_vty.c \
bfdd/bfdd_cli.c \
bfdd/bfd_packet.c \ bfdd/bfd_packet.c \
bfdd/config.c \ bfdd/config.c \
bfdd/control.c \ bfdd/control.c \
@ -24,6 +27,9 @@ bfdd_libbfd_a_SOURCES = \
bfdd/bfdd_vty_clippy.c: $(CLIPPY_DEPS) bfdd/bfdd_vty_clippy.c: $(CLIPPY_DEPS)
bfdd/bfdd_vty.$(OBJEXT): bfdd/bfdd_vty_clippy.c bfdd/bfdd_vty.$(OBJEXT): bfdd/bfdd_vty_clippy.c
bfdd/bfdd_cli_clippy.c: $(CLIPPY_DEPS)
bfdd/bfdd_cli.$(OBJEXT): bfdd/bfdd_cli_clippy.c
noinst_HEADERS += \ noinst_HEADERS += \
bfdd/bfdctl.h \ bfdd/bfdctl.h \
bfdd/bfd.h \ bfdd/bfd.h \

View file

@ -24,6 +24,10 @@ dist_yangmodels_DATA += yang/frr-test-module.yang
dist_yangmodels_DATA += yang/frr-interface.yang dist_yangmodels_DATA += yang/frr-interface.yang
dist_yangmodels_DATA += yang/frr-route-types.yang dist_yangmodels_DATA += yang/frr-route-types.yang
if BFDD
dist_yangmodels_DATA += yang/frr-bfdd.yang
endif
if RIPD if RIPD
dist_yangmodels_DATA += yang/frr-ripd.yang dist_yangmodels_DATA += yang/frr-ripd.yang
endif endif