forked from Mirror/frr
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:
parent
3e4e7405ff
commit
adc26455bf
78
bfdd/bfd.c
78
bfdd/bfd.c
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
23
bfdd/bfd.h
23
bfdd/bfd.h
|
@ -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_ */
|
||||||
|
|
|
@ -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
232
bfdd/bfdd_cli.c
Normal 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
1060
bfdd/bfdd_northbound.c
Normal file
File diff suppressed because it is too large
Load diff
264
bfdd/bfdd_vty.c
264
bfdd/bfdd_vty.c
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue