mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-01-03 23:00:44 +00:00
commit
ace430f0db
11
bfdd/bfd.c
11
bfdd/bfd.c
@ -600,6 +600,17 @@ skip_echo:
|
||||
bfd_recvtimer_update(bs);
|
||||
bfd_xmttimer_update(bs, bs->xmt_TO);
|
||||
}
|
||||
if (bpc->bpc_cbit) {
|
||||
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CBIT))
|
||||
return;
|
||||
|
||||
BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CBIT);
|
||||
} else {
|
||||
if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CBIT))
|
||||
return;
|
||||
|
||||
BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CBIT);
|
||||
}
|
||||
}
|
||||
|
||||
static int bfd_session_update(struct bfd_session *bs, struct bfd_peer_cfg *bpc)
|
||||
|
||||
@ -129,6 +129,12 @@ struct bfd_echo_pkt {
|
||||
flags |= (val & 0x3) << 6; \
|
||||
}
|
||||
#define BFD_GETSTATE(flags) ((flags >> 6) & 0x3)
|
||||
#define BFD_SETCBIT(flags, val) \
|
||||
{ \
|
||||
if ((val)) \
|
||||
flags |= val; \
|
||||
}
|
||||
#define BFD_GETCBIT(flags) (flags & BFD_FBIT)
|
||||
#define BFD_ECHO_VERSION 1
|
||||
#define BFD_ECHO_PKT_LEN sizeof(struct bfd_echo_pkt)
|
||||
|
||||
@ -168,6 +174,7 @@ enum bfd_session_flags {
|
||||
*/
|
||||
BFD_SESS_FLAG_SHUTDOWN = 1 << 7, /* disable BGP peer function */
|
||||
BFD_SESS_FLAG_CONFIG = 1 << 8, /* Session configured with bfd NB API */
|
||||
BFD_SESS_FLAG_CBIT = 1 << 9, /* CBIT is set */
|
||||
};
|
||||
|
||||
#define BFD_SET_FLAG(field, flag) (field |= flag)
|
||||
@ -210,6 +217,7 @@ struct bfd_session {
|
||||
uint8_t detect_mult;
|
||||
uint8_t remote_detect_mult;
|
||||
uint8_t mh_ttl;
|
||||
uint8_t remote_cbit;
|
||||
|
||||
/* Timers */
|
||||
struct bfd_timers timers;
|
||||
|
||||
@ -221,6 +221,10 @@ void ptm_bfd_snd(struct bfd_session *bfd, int fbit)
|
||||
BFD_SETVER(cp.diag, BFD_VERSION);
|
||||
cp.flags = 0;
|
||||
BFD_SETSTATE(cp.flags, bfd->ses_state);
|
||||
|
||||
if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_CBIT))
|
||||
BFD_SETCBIT(cp.flags, BFD_CBIT);
|
||||
|
||||
BFD_SETDEMANDBIT(cp.flags, BFD_DEF_DEMAND);
|
||||
|
||||
/*
|
||||
@ -646,6 +650,11 @@ int bfd_recv_cb(struct thread *t)
|
||||
ntohl(cp->timers.required_min_echo);
|
||||
bfd->remote_detect_mult = cp->detect_mult;
|
||||
|
||||
if (BFD_GETCBIT(cp->flags))
|
||||
bfd->remote_cbit = 1;
|
||||
else
|
||||
bfd->remote_cbit = 0;
|
||||
|
||||
/* State switch from section 6.2. */
|
||||
bs_state_handler(bfd, BFD_GETSTATE(cp->flags));
|
||||
|
||||
|
||||
@ -88,6 +88,8 @@ struct bfd_peer_cfg {
|
||||
bool bpc_createonly;
|
||||
bool bpc_shutdown;
|
||||
|
||||
bool bpc_cbit;
|
||||
|
||||
/* Status information */
|
||||
enum bfd_peer_status bpc_bps;
|
||||
uint32_t bpc_id;
|
||||
|
||||
@ -89,6 +89,7 @@ static void debug_printbpc(const char *func, unsigned int line,
|
||||
{
|
||||
char addr[3][128];
|
||||
char timers[3][128];
|
||||
char cbit_str[10];
|
||||
|
||||
addr[0][0] = addr[1][0] = addr[2][0] = timers[0][0] = timers[1][0] =
|
||||
timers[2][0] = 0;
|
||||
@ -117,9 +118,11 @@ static void debug_printbpc(const char *func, unsigned int line,
|
||||
snprintf(timers[2], sizeof(timers[2]), " detect-multiplier:%d",
|
||||
bpc->bpc_detectmultiplier);
|
||||
|
||||
log_debug("%s:%d: %s %s%s%s%s%s%s", func, line,
|
||||
sprintf(cbit_str, "CB %x", bpc->bpc_cbit);
|
||||
|
||||
log_debug("%s:%d: %s %s%s%s%s%s%s %s", func, line,
|
||||
bpc->bpc_mhop ? "multi-hop" : "single-hop", addr[0], addr[1],
|
||||
addr[2], timers[0], timers[1], timers[2]);
|
||||
addr[2], timers[0], timers[1], timers[2], cbit_str);
|
||||
}
|
||||
|
||||
#define DEBUG_PRINTBPC(bpc) debug_printbpc(__FILE__, __LINE__, (bpc))
|
||||
@ -173,6 +176,7 @@ int ptm_bfd_notify(struct bfd_session *bs)
|
||||
* - AF_INET6:
|
||||
* - 16 bytes: ipv6
|
||||
* - c: prefix length
|
||||
* - c: cbit
|
||||
*
|
||||
* Commands: ZEBRA_BFD_DEST_REPLAY
|
||||
*
|
||||
@ -219,6 +223,8 @@ int ptm_bfd_notify(struct bfd_session *bs)
|
||||
/* BFD source prefix information. */
|
||||
_ptm_msg_address(msg, bs->key.family, &bs->key.local);
|
||||
|
||||
stream_putc(msg, bs->remote_cbit);
|
||||
|
||||
/* Write packet size. */
|
||||
stream_putw_at(msg, 0, stream_get_endp(msg));
|
||||
|
||||
@ -293,6 +299,7 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
|
||||
* - 16 bytes: ipv6 address
|
||||
* - c: ifname length
|
||||
* - X bytes: interface name
|
||||
* - c: bfd_cbit
|
||||
*
|
||||
* q(64), l(32), w(16), c(8)
|
||||
*/
|
||||
@ -371,6 +378,8 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
|
||||
}
|
||||
}
|
||||
|
||||
STREAM_GETC(msg, bpc->bpc_cbit);
|
||||
|
||||
/* Sanity check: peer and local address must match IP types. */
|
||||
if (bpc->bpc_local.sa_sin.sin_family != 0
|
||||
&& (bpc->bpc_local.sa_sin.sin_family
|
||||
|
||||
118
bgpd/bgp_bfd.c
118
bgpd/bgp_bfd.c
@ -96,7 +96,7 @@ int bgp_bfd_is_peer_multihop(struct peer *peer)
|
||||
static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
|
||||
{
|
||||
struct bfd_info *bfd_info;
|
||||
int multihop;
|
||||
int multihop, cbit = 0;
|
||||
vrf_id_t vrf_id;
|
||||
|
||||
bfd_info = (struct bfd_info *)peer->bfd_info;
|
||||
@ -112,20 +112,30 @@ static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
|
||||
if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop)
|
||||
SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
|
||||
}
|
||||
/* while graceful restart with fwd path preserved
|
||||
* and bfd controlplane check not configured is not kept
|
||||
* keep bfd independent controlplane bit set to 1
|
||||
*/
|
||||
if (!bgp_flag_check(peer->bgp, BGP_FLAG_GRACEFUL_RESTART)
|
||||
&& !bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD)
|
||||
&& !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE))
|
||||
SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
|
||||
|
||||
cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
|
||||
|
||||
if (peer->su.sa.sa_family == AF_INET)
|
||||
bfd_peer_sendmsg(
|
||||
zclient, bfd_info, AF_INET, &peer->su.sin.sin_addr,
|
||||
(peer->su_local) ? &peer->su_local->sin.sin_addr : NULL,
|
||||
(peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
|
||||
peer->ttl, multihop, command, 1, vrf_id);
|
||||
peer->ttl, multihop, cbit, command, 1, vrf_id);
|
||||
else if (peer->su.sa.sa_family == AF_INET6)
|
||||
bfd_peer_sendmsg(
|
||||
zclient, bfd_info, AF_INET6, &peer->su.sin6.sin6_addr,
|
||||
(peer->su_local) ? &peer->su_local->sin6.sin6_addr
|
||||
: NULL,
|
||||
(peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
|
||||
peer->ttl, multihop, command, 1, vrf_id);
|
||||
peer->ttl, multihop, cbit, command, 1, vrf_id);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -260,7 +270,8 @@ static int bgp_bfd_dest_replay(ZAPI_CALLBACK_ARGS)
|
||||
* down the peer if the BFD session went down from
|
||||
* * up.
|
||||
*/
|
||||
static void bgp_bfd_peer_status_update(struct peer *peer, int status)
|
||||
static void bgp_bfd_peer_status_update(struct peer *peer, int status,
|
||||
int remote_cbit)
|
||||
{
|
||||
struct bfd_info *bfd_info;
|
||||
int old_status;
|
||||
@ -280,6 +291,14 @@ static void bgp_bfd_peer_status_update(struct peer *peer, int status)
|
||||
bfd_get_status_str(status));
|
||||
}
|
||||
if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) {
|
||||
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE) &&
|
||||
CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE) &&
|
||||
!remote_cbit) {
|
||||
zlog_info("%s BFD DOWN message ignored in the process"
|
||||
" of graceful restart when C bit is cleared",
|
||||
peer->host);
|
||||
return;
|
||||
}
|
||||
peer->last_reset = PEER_DOWN_BFD_DOWN;
|
||||
BGP_EVENT_ADD(peer, BGP_Stop);
|
||||
}
|
||||
@ -303,23 +322,27 @@ static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS)
|
||||
struct prefix dp;
|
||||
struct prefix sp;
|
||||
int status;
|
||||
int remote_cbit;
|
||||
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id);
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status,
|
||||
&remote_cbit, vrf_id);
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA)) {
|
||||
char buf[2][PREFIX2STR_BUFFER];
|
||||
prefix2str(&dp, buf[0], sizeof(buf[0]));
|
||||
if (ifp) {
|
||||
zlog_debug(
|
||||
"Zebra: vrf %u interface %s bfd destination %s %s",
|
||||
"Zebra: vrf %u interface %s bfd destination %s %s %s",
|
||||
vrf_id, ifp->name, buf[0],
|
||||
bfd_get_status_str(status));
|
||||
bfd_get_status_str(status),
|
||||
remote_cbit ? "(cbit on)" : "");
|
||||
} else {
|
||||
prefix2str(&sp, buf[1], sizeof(buf[1]));
|
||||
zlog_debug(
|
||||
"Zebra: vrf %u source %s bfd destination %s %s",
|
||||
"Zebra: vrf %u source %s bfd destination %s %s %s",
|
||||
vrf_id, buf[1], buf[0],
|
||||
bfd_get_status_str(status));
|
||||
bfd_get_status_str(status),
|
||||
remote_cbit ? "(cbit on)" : "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,7 +374,8 @@ static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS)
|
||||
|
||||
if (ifp && (ifp == peer->nexthop.ifp)) {
|
||||
bgp_bfd_peer_status_update(peer,
|
||||
status);
|
||||
status,
|
||||
remote_cbit);
|
||||
} else {
|
||||
if (!peer->su_local)
|
||||
continue;
|
||||
@ -381,7 +405,8 @@ static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS)
|
||||
continue;
|
||||
|
||||
bgp_bfd_peer_status_update(peer,
|
||||
status);
|
||||
status,
|
||||
remote_cbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,6 +559,9 @@ void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
|
||||
if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)
|
||||
&& (bfd_info->type == BFD_TYPE_NOT_CONFIGURED))
|
||||
vty_out(vty, " neighbor %s bfd\n", addr);
|
||||
|
||||
if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE))
|
||||
vty_out(vty, " neighbor %s bfd check-control-plane-failure\n", addr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -644,6 +672,73 @@ DEFUN_HIDDEN (neighbor_bfd_type,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int bgp_bfd_set_check_controlplane_failure_peer(struct vty *vty, struct peer *peer,
|
||||
const char *no)
|
||||
{
|
||||
struct bfd_info *bfd_info;
|
||||
|
||||
if (!peer->bfd_info) {
|
||||
if (no)
|
||||
return CMD_SUCCESS;
|
||||
vty_out(vty, "%% Specify bfd command first\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
bfd_info = (struct bfd_info *)peer->bfd_info;
|
||||
if (!no) {
|
||||
if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) {
|
||||
SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE);
|
||||
bgp_bfd_update_peer(peer);
|
||||
}
|
||||
} else {
|
||||
if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) {
|
||||
UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE);
|
||||
bgp_bfd_update_peer(peer);
|
||||
}
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN (neighbor_bfd_check_controlplane_failure,
|
||||
neighbor_bfd_check_controlplane_failure_cmd,
|
||||
"[no] neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"BFD support\n"
|
||||
"Link dataplane status with BGP controlplane\n")
|
||||
{
|
||||
const char *no = strmatch(argv[0]->text, "no") ? "no" : NULL;
|
||||
int idx_peer = 0;
|
||||
struct peer *peer;
|
||||
struct peer_group *group;
|
||||
struct listnode *node, *nnode;
|
||||
int ret = CMD_SUCCESS;
|
||||
|
||||
if (no)
|
||||
idx_peer = 2;
|
||||
else
|
||||
idx_peer = 1;
|
||||
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
|
||||
if (!peer) {
|
||||
vty_out(vty, "%% Specify remote-as or peer-group commands first\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (!peer->bfd_info) {
|
||||
if (no)
|
||||
return CMD_SUCCESS;
|
||||
vty_out(vty, "%% Specify bfd command first\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
|
||||
group = peer->group;
|
||||
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer))
|
||||
ret = bgp_bfd_set_check_controlplane_failure_peer(vty, peer, no);
|
||||
} else
|
||||
ret = bgp_bfd_set_check_controlplane_failure_peer(vty, peer, no);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFUN (no_neighbor_bfd,
|
||||
no_neighbor_bfd_cmd,
|
||||
#if HAVE_BFDD > 0
|
||||
@ -718,6 +813,7 @@ void bgp_bfd_init(void)
|
||||
install_element(BGP_NODE, &neighbor_bfd_cmd);
|
||||
install_element(BGP_NODE, &neighbor_bfd_param_cmd);
|
||||
install_element(BGP_NODE, &neighbor_bfd_type_cmd);
|
||||
install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd);
|
||||
install_element(BGP_NODE, &no_neighbor_bfd_cmd);
|
||||
install_element(BGP_NODE, &no_neighbor_bfd_type_cmd);
|
||||
}
|
||||
|
||||
@ -1115,8 +1115,6 @@ int bgp_stop(struct peer *peer)
|
||||
|
||||
/* Reset peer synctime */
|
||||
peer->synctime = 0;
|
||||
|
||||
bgp_bfd_deregister_peer(peer);
|
||||
}
|
||||
|
||||
/* stop keepalives */
|
||||
|
||||
@ -174,6 +174,21 @@ The following commands are available inside the BGP configuration node.
|
||||
|
||||
Removes any notification registration for this neighbor.
|
||||
|
||||
.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure
|
||||
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure
|
||||
|
||||
Allow to write CBIT independence in BFD outgoing packets. Also allow to
|
||||
read both C-BIT value of BFD and lookup BGP peer status. This command is
|
||||
useful when a BFD down event is caught, while the BGP peer requested that
|
||||
local BGP keeps the remote BGP entries as staled if such issue is detected.
|
||||
This is the case when graceful restart is enabled, and it is wished to
|
||||
ignore the BD event while waiting for the remote router to restart.
|
||||
|
||||
.. index:: no neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure
|
||||
.. clicmd:: no neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure
|
||||
|
||||
Disallow to write CBIT independence in BFD outgoing packets. Also disallow
|
||||
to ignore BFD down notification. This is the default behaviour.
|
||||
|
||||
.. _bfd-ospf-peer-config:
|
||||
|
||||
|
||||
@ -98,7 +98,8 @@ static int isis_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
|
||||
struct prefix dst_ip;
|
||||
int status;
|
||||
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status, vrf_id);
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status,
|
||||
NULL, vrf_id);
|
||||
if (!ifp || dst_ip.family != AF_INET)
|
||||
return 0;
|
||||
|
||||
@ -217,6 +218,7 @@ static void bfd_handle_adj_down(struct isis_adjacency *adj)
|
||||
adj->circuit->interface->name,
|
||||
0, /* ttl */
|
||||
0, /* multihop */
|
||||
1, /* control plane independent bit is on */
|
||||
ZEBRA_BFD_DEST_DEREGISTER,
|
||||
0, /* set_flag */
|
||||
VRF_DEFAULT);
|
||||
@ -258,6 +260,7 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj, int command)
|
||||
circuit->interface->name,
|
||||
0, /* ttl */
|
||||
0, /* multihop */
|
||||
1, /* control plane independent bit is on */
|
||||
command,
|
||||
0, /* set flag */
|
||||
VRF_DEFAULT);
|
||||
|
||||
14
lib/bfd.c
14
lib/bfd.c
@ -127,8 +127,8 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx,
|
||||
*/
|
||||
void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info,
|
||||
int family, void *dst_ip, void *src_ip, char *if_name,
|
||||
int ttl, int multihop, int command, int set_flag,
|
||||
vrf_id_t vrf_id)
|
||||
int ttl, int multihop, int cbit, int command,
|
||||
int set_flag, vrf_id_t vrf_id)
|
||||
{
|
||||
struct stream *s;
|
||||
int ret;
|
||||
@ -208,6 +208,11 @@ void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info,
|
||||
stream_putc(s, 0);
|
||||
}
|
||||
}
|
||||
/* cbit */
|
||||
if (cbit)
|
||||
stream_putc(s, 1);
|
||||
else
|
||||
stream_putc(s, 0);
|
||||
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
@ -253,11 +258,13 @@ const char *bfd_get_command_dbg_str(int command)
|
||||
*/
|
||||
struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
|
||||
struct prefix *sp, int *status,
|
||||
int *remote_cbit,
|
||||
vrf_id_t vrf_id)
|
||||
{
|
||||
unsigned int ifindex;
|
||||
struct interface *ifp = NULL;
|
||||
int plen;
|
||||
int local_remote_cbit;
|
||||
|
||||
/* Get interface index. */
|
||||
ifindex = stream_getl(s);
|
||||
@ -292,6 +299,9 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
|
||||
stream_get(&sp->u.prefix, s, plen);
|
||||
sp->prefixlen = stream_getc(s);
|
||||
}
|
||||
local_remote_cbit = stream_getc(s);
|
||||
if (remote_cbit)
|
||||
*remote_cbit = local_remote_cbit;
|
||||
return ifp;
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,8 @@ struct bfd_gbl {
|
||||
#define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */
|
||||
#define BFD_FLAG_BFD_REG (1 << 1) /* Peer registered with BFD */
|
||||
#define BFD_FLAG_BFD_TYPE_MULTIHOP (1 << 2) /* Peer registered with BFD as multihop */
|
||||
#define BFD_FLAG_BFD_CBIT_ON (1 << 3) /* Peer registered with CBIT set to on */
|
||||
#define BFD_FLAG_BFD_CHECK_CONTROLPLANE (1 << 4) /* BFD and controlplane daemon are linked */
|
||||
|
||||
#define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */
|
||||
#define BFD_STATUS_DOWN (1 << 1) /* BFD session status is down */
|
||||
@ -83,13 +85,14 @@ extern void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx,
|
||||
int *command);
|
||||
extern void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info,
|
||||
int family, void *dst_ip, void *src_ip,
|
||||
char *if_name, int ttl, int multihop, int command,
|
||||
int set_flag, vrf_id_t vrf_id);
|
||||
char *if_name, int ttl, int multihop, int cbit,
|
||||
int command, int set_flag, vrf_id_t vrf_id);
|
||||
|
||||
extern const char *bfd_get_command_dbg_str(int command);
|
||||
|
||||
extern struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
|
||||
struct prefix *sp, int *status,
|
||||
int *remote_cbit,
|
||||
vrf_id_t vrf_id);
|
||||
|
||||
const char *bfd_get_status_str(int status);
|
||||
|
||||
@ -74,6 +74,7 @@ void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command)
|
||||
struct interface *ifp = oi->interface;
|
||||
struct bfd_info *bfd_info;
|
||||
char src[64];
|
||||
int cbit;
|
||||
|
||||
if (!oi->bfd_info || !on->bfd_info)
|
||||
return;
|
||||
@ -85,9 +86,11 @@ void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command)
|
||||
bfd_get_command_dbg_str(command), src);
|
||||
}
|
||||
|
||||
cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
|
||||
|
||||
bfd_peer_sendmsg(zclient, bfd_info, AF_INET6, &on->linklocal_addr,
|
||||
on->ospf6_if->linklocal_addr, ifp->name, 0, 0, command,
|
||||
0, VRF_DEFAULT);
|
||||
on->ospf6_if->linklocal_addr, ifp->name, 0, 0,
|
||||
cbit, command, 0, VRF_DEFAULT);
|
||||
|
||||
if (command == ZEBRA_BFD_DEST_DEREGISTER)
|
||||
bfd_info_free((struct bfd_info **)&on->bfd_info);
|
||||
@ -195,7 +198,8 @@ static int ospf6_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
|
||||
struct bfd_info *bfd_info;
|
||||
struct timeval tv;
|
||||
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id);
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status,
|
||||
NULL, vrf_id);
|
||||
|
||||
if ((ifp == NULL) || (dp.family != AF_INET6))
|
||||
return 0;
|
||||
|
||||
@ -65,6 +65,7 @@ static void ospf_bfd_reg_dereg_nbr(struct ospf_neighbor *nbr, int command)
|
||||
struct interface *ifp = oi->ifp;
|
||||
struct ospf_if_params *params;
|
||||
struct bfd_info *bfd_info;
|
||||
int cbit;
|
||||
|
||||
/* Check if BFD is enabled */
|
||||
params = IF_DEF_PARAMS(ifp);
|
||||
@ -80,8 +81,10 @@ static void ospf_bfd_reg_dereg_nbr(struct ospf_neighbor *nbr, int command)
|
||||
inet_ntoa(nbr->src),
|
||||
ospf_vrf_id_to_name(oi->ospf->vrf_id));
|
||||
|
||||
cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
|
||||
|
||||
bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->src, NULL, ifp->name,
|
||||
0, 0, command, 0, oi->ospf->vrf_id);
|
||||
0, 0, cbit, command, 0, oi->ospf->vrf_id);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -207,7 +210,8 @@ static int ospf_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
|
||||
struct bfd_info *bfd_info;
|
||||
struct timeval tv;
|
||||
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, vrf_id);
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status,
|
||||
NULL, vrf_id);
|
||||
|
||||
if ((ifp == NULL) || (p.family != AF_INET))
|
||||
return 0;
|
||||
|
||||
@ -111,6 +111,7 @@ static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command)
|
||||
struct pim_interface *pim_ifp = NULL;
|
||||
struct bfd_info *bfd_info = NULL;
|
||||
struct zclient *zclient = NULL;
|
||||
int cbit;
|
||||
|
||||
zclient = pim_zebra_zclient_get();
|
||||
|
||||
@ -127,8 +128,12 @@ static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command)
|
||||
zlog_debug("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__, str,
|
||||
bfd_get_command_dbg_str(command));
|
||||
}
|
||||
|
||||
cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
|
||||
|
||||
bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->source_addr, NULL,
|
||||
nbr->interface->name, 0, 0, command, 0, VRF_DEFAULT);
|
||||
nbr->interface->name, 0, 0, cbit,
|
||||
command, 0, VRF_DEFAULT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -222,7 +227,8 @@ static int pim_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
|
||||
struct listnode *neigh_nextnode = NULL;
|
||||
struct pim_neighbor *neigh = NULL;
|
||||
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, vrf_id);
|
||||
ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status,
|
||||
NULL, vrf_id);
|
||||
|
||||
if ((ifp == NULL) || (p.family != AF_INET))
|
||||
return 0;
|
||||
|
||||
0
tests/topotests/bfd-bgp-cbit-topo3/__init__.py
Normal file
0
tests/topotests/bfd-bgp-cbit-topo3/__init__.py
Normal file
103
tests/topotests/bfd-bgp-cbit-topo3/r1/bgp_ipv6_routes_down.json
Normal file
103
tests/topotests/bfd-bgp-cbit-topo3/r1/bgp_ipv6_routes_down.json
Normal file
@ -0,0 +1,103 @@
|
||||
{
|
||||
"vrfId": 0,
|
||||
"vrfName": "default",
|
||||
"routerId": "10.254.254.1",
|
||||
"localAS": 101,
|
||||
"routes":
|
||||
{
|
||||
"2001:db8:6::/64": [
|
||||
{
|
||||
"stale": true,
|
||||
"valid": true,
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"prefix": "2001:db8:6::",
|
||||
"prefixLen": 64,
|
||||
"network": "2001:db8:6::\/64",
|
||||
"med": 0,
|
||||
"metric": 0,
|
||||
"weight": 0,
|
||||
"peerId": "2001:db8:4::1",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{ "ip": "2001:db8:4::1",
|
||||
"afi": "ipv6",
|
||||
"scope": "global",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:7::/64": [
|
||||
{
|
||||
"stale": true,
|
||||
"valid": true,
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"prefix": "2001:db8:7::",
|
||||
"prefixLen": 64, "network":
|
||||
"2001:db8:7::\/64",
|
||||
"med": 0,
|
||||
"metric": 0,
|
||||
"weight": 0,
|
||||
"peerId": "2001:db8:4::1",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "2001:db8:4::1",
|
||||
"afi": "ipv6",
|
||||
"scope": "global",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:8::/64": [
|
||||
{
|
||||
"valid": true,
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"prefix": "2001:db8:8::",
|
||||
"prefixLen": 64,
|
||||
"network": "2001:db8:8::\/64",
|
||||
"med": 0,
|
||||
"metric": 0,
|
||||
"weight": 32768,
|
||||
"peerId": "(unspec)",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "::",
|
||||
"afi": "ipv6",
|
||||
"scope": "global",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:9::/64": [
|
||||
{
|
||||
"valid": true,
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"prefix": "2001:db8:9::",
|
||||
"prefixLen": 64,
|
||||
"network": "2001:db8:9::\/64",
|
||||
"med": 0,
|
||||
"metric": 0,
|
||||
"weight": 32768,
|
||||
"peerId": "(unspec)",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "::",
|
||||
"afi": "ipv6",
|
||||
"scope": "global",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
20
tests/topotests/bfd-bgp-cbit-topo3/r1/bgpd.conf
Normal file
20
tests/topotests/bfd-bgp-cbit-topo3/r1/bgpd.conf
Normal file
@ -0,0 +1,20 @@
|
||||
debug bgp neighbor-events
|
||||
router bgp 101
|
||||
bgp router-id 10.254.254.1
|
||||
timers bgp 8 24
|
||||
bgp graceful-restart
|
||||
neighbor 2001:db8:4::1 remote-as 102
|
||||
neighbor 2001:db8:4::1 remote-as external
|
||||
neighbor 2001:db8:4::1 bfd
|
||||
neighbor 2001:db8:4::1 bfd check-control-plane-failure
|
||||
neighbor 2001:db8:4::1 update-source 2001:db8:1::1
|
||||
neighbor 2001:db8:4::1 ebgp-multihop 5
|
||||
address-family ipv4 unicast
|
||||
no neighbor 2001:db8:4::1 activate
|
||||
exit-address-family
|
||||
address-family ipv6 unicast
|
||||
network 2001:db8:8::/64
|
||||
network 2001:db8:9::/64
|
||||
neighbor 2001:db8:4::1 activate
|
||||
exit-address-family
|
||||
!
|
||||
80
tests/topotests/bfd-bgp-cbit-topo3/r1/ipv6_routes.json
Normal file
80
tests/topotests/bfd-bgp-cbit-topo3/r1/ipv6_routes.json
Normal file
@ -0,0 +1,80 @@
|
||||
{
|
||||
"2001:db8:1::/64": [{
|
||||
"distance": 0,
|
||||
"protocol": "connected",
|
||||
"metric": 0,
|
||||
"selected": true,
|
||||
"destSelected": true,
|
||||
"prefix": "2001:db8:1::/64",
|
||||
"nexthops": [{
|
||||
"directlyConnected": true,
|
||||
"interfaceName": "r1-eth0",
|
||||
"fib": true,
|
||||
"flags": 3,
|
||||
"active": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:4::/64": [{
|
||||
"distance": 1,
|
||||
"protocol": "static",
|
||||
"metric": 0,
|
||||
"selected": true,
|
||||
"destSelected": true,
|
||||
"prefix": "2001:db8:4::/64",
|
||||
"nexthops": [{
|
||||
"interfaceName": "r1-eth0",
|
||||
"fib": true,
|
||||
"flags": 3,
|
||||
"active": true,
|
||||
"afi": "ipv6"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:6::/64": [{
|
||||
"distance": 20,
|
||||
"protocol": "bgp",
|
||||
"metric": 0,
|
||||
"selected": true,
|
||||
"destSelected": true,
|
||||
"prefix": "2001:db8:6::/64",
|
||||
"nexthops": [{
|
||||
"ip":"2001:db8:4::1",
|
||||
"active": true,
|
||||
"afi": "ipv6",
|
||||
"recursive":true
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"2001:db8:1::2",
|
||||
"afi": "ipv6",
|
||||
"interfaceName": "r1-eth0"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:7::/64": [{
|
||||
"distance": 20,
|
||||
"protocol": "bgp",
|
||||
"metric": 0,
|
||||
"selected": true,
|
||||
"destSelected": true,
|
||||
"prefix": "2001:db8:7::/64",
|
||||
"nexthops": [{
|
||||
"ip":"2001:db8:4::1",
|
||||
"active": true,
|
||||
"afi": "ipv6",
|
||||
"recursive": true
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"2001:db8:1::2",
|
||||
"afi": "ipv6",
|
||||
"interfaceName":"r1-eth0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
16
tests/topotests/bfd-bgp-cbit-topo3/r1/peers.json
Normal file
16
tests/topotests/bfd-bgp-cbit-topo3/r1/peers.json
Normal file
@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"multihop":true,
|
||||
"peer":"2001:db8:4::1",
|
||||
"local":"2001:db8:1::1",
|
||||
"status":"up",
|
||||
"diagnostic":"ok",
|
||||
"remote-diagnostic":"ok",
|
||||
"receive-interval":300,
|
||||
"transmit-interval":300,
|
||||
"echo-interval":0,
|
||||
"remote-receive-interval":300,
|
||||
"remote-transmit-interval":300,
|
||||
"remote-echo-interval":50
|
||||
}
|
||||
]
|
||||
14
tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json
Normal file
14
tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json
Normal file
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"multihop":true,
|
||||
"peer":"2001:db8:4::1",
|
||||
"local":"2001:db8:1::1",
|
||||
"status":"up",
|
||||
"receive-interval":300,
|
||||
"transmit-interval":300,
|
||||
"echo-interval":0,
|
||||
"remote-receive-interval":300,
|
||||
"remote-transmit-interval":300,
|
||||
"remote-echo-interval":50
|
||||
}
|
||||
]
|
||||
8
tests/topotests/bfd-bgp-cbit-topo3/r1/zebra.conf
Normal file
8
tests/topotests/bfd-bgp-cbit-topo3/r1/zebra.conf
Normal file
@ -0,0 +1,8 @@
|
||||
interface lo
|
||||
ip address 10.254.254.1/32
|
||||
!
|
||||
interface r1-eth0
|
||||
ipv6 address 2001:db8:1::1/64
|
||||
!
|
||||
ipv6 route 2001:db8:4::/64 2001:db8:1::2
|
||||
|
||||
9
tests/topotests/bfd-bgp-cbit-topo3/r2/zebra.conf
Normal file
9
tests/topotests/bfd-bgp-cbit-topo3/r2/zebra.conf
Normal file
@ -0,0 +1,9 @@
|
||||
ip forwarding
|
||||
ipv6 forwarding
|
||||
!
|
||||
interface r2-eth0
|
||||
ipv6 address 2001:db8:1::2/64
|
||||
!
|
||||
interface r2-eth1
|
||||
ipv6 address 2001:db8:4::2/64
|
||||
!
|
||||
@ -0,0 +1,55 @@
|
||||
{
|
||||
"vrfId": 0,
|
||||
"vrfName": "default",
|
||||
"routerId": "10.254.254.3",
|
||||
"localAS": 102,
|
||||
"routes":
|
||||
{
|
||||
"2001:db8:6::/64": [
|
||||
{
|
||||
"valid": true,
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"prefix": "2001:db8:6::",
|
||||
"prefixLen": 64,
|
||||
"network": "2001:db8:6::\/64",
|
||||
"med": 0,
|
||||
"metric": 0,
|
||||
"weight": 32768,
|
||||
"peerId": "(unspec)",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "::",
|
||||
"afi": "ipv6",
|
||||
"scope": "global",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:7::/64": [
|
||||
{
|
||||
"valid": true,
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"prefix": "2001:db8:7::",
|
||||
"prefixLen": 64,
|
||||
"network": "2001:db8:7::\/64",
|
||||
"med": 0,
|
||||
"metric": 0,
|
||||
"weight": 32768,
|
||||
"peerId": "(unspec)",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "::",
|
||||
"afi": "ipv6",
|
||||
"scope": "global",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
25
tests/topotests/bfd-bgp-cbit-topo3/r3/bgpd.conf
Normal file
25
tests/topotests/bfd-bgp-cbit-topo3/r3/bgpd.conf
Normal file
@ -0,0 +1,25 @@
|
||||
debug bgp neighbor-events
|
||||
router bgp 102
|
||||
bgp router-id 10.254.254.3
|
||||
timers bgp 20 60
|
||||
bgp graceful-restart
|
||||
! simulate NSF machine
|
||||
bgp graceful-restart preserve-fw-state
|
||||
bgp graceful-restart stalepath-time 900
|
||||
bgp graceful-restart restart-time 900
|
||||
neighbor 2001:db8:1::1 remote-as 101
|
||||
neighbor 2001:db8:1::1 remote-as external
|
||||
neighbor 2001:db8:1::1 update-source 2001:db8:4::1
|
||||
neighbor 2001:db8:1::1 bfd
|
||||
neighbor 2001:db8:1::1 ebgp-multihop 5
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
no neighbor 2001:db8:1::1 activate
|
||||
exit-address-family
|
||||
!
|
||||
address-family ipv6 unicast
|
||||
neighbor 2001:db8:1::1 activate
|
||||
network 2001:db8:6::/64
|
||||
network 2001:db8:7::/64
|
||||
exit-address-family
|
||||
!
|
||||
80
tests/topotests/bfd-bgp-cbit-topo3/r3/ipv6_routes.json
Normal file
80
tests/topotests/bfd-bgp-cbit-topo3/r3/ipv6_routes.json
Normal file
@ -0,0 +1,80 @@
|
||||
{
|
||||
"2001:db8:1::/64": [{
|
||||
"distance": 1,
|
||||
"protocol": "static",
|
||||
"metric": 0,
|
||||
"selected": true,
|
||||
"destSelected": true,
|
||||
"prefix": "2001:db8:1::/64",
|
||||
"nexthops": [{
|
||||
"interfaceName": "r3-eth0",
|
||||
"fib": true,
|
||||
"flags": 3,
|
||||
"active": true,
|
||||
"afi": "ipv6"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:4::/64": [{
|
||||
"distance": 0,
|
||||
"protocol": "connected",
|
||||
"metric": 0,
|
||||
"selected": true,
|
||||
"destSelected": true,
|
||||
"prefix": "2001:db8:4::/64",
|
||||
"nexthops": [{
|
||||
"directlyConnected": true,
|
||||
"interfaceName": "r3-eth0",
|
||||
"fib": true,
|
||||
"flags": 3,
|
||||
"active": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:8::/64": [{
|
||||
"distance": 20,
|
||||
"protocol": "bgp",
|
||||
"metric": 0,
|
||||
"selected": true,
|
||||
"destSelected": true,
|
||||
"prefix": "2001:db8:8::/64",
|
||||
"nexthops": [{
|
||||
"ip":"2001:db8:1::1",
|
||||
"active": true,
|
||||
"afi": "ipv6",
|
||||
"recursive":true
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"2001:db8:4::2",
|
||||
"afi": "ipv6",
|
||||
"interfaceName":"r3-eth0"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2001:db8:9::/64": [{
|
||||
"distance": 20,
|
||||
"protocol": "bgp",
|
||||
"metric": 0,
|
||||
"selected": true,
|
||||
"destSelected": true,
|
||||
"prefix": "2001:db8:9::/64",
|
||||
"nexthops": [{
|
||||
"ip":"2001:db8:1::1",
|
||||
"active": true,
|
||||
"afi": "ipv6",
|
||||
"recursive":true
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"2001:db8:4::2",
|
||||
"afi": "ipv6",
|
||||
"interfaceName":"r3-eth0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
16
tests/topotests/bfd-bgp-cbit-topo3/r3/peers.json
Normal file
16
tests/topotests/bfd-bgp-cbit-topo3/r3/peers.json
Normal file
@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"multihop":true,
|
||||
"peer":"2001:db8:1::1",
|
||||
"local":"2001:db8:4::1",
|
||||
"status":"up",
|
||||
"diagnostic":"ok",
|
||||
"remote-diagnostic":"ok",
|
||||
"receive-interval":300,
|
||||
"transmit-interval":300,
|
||||
"echo-interval":0,
|
||||
"remote-receive-interval":300,
|
||||
"remote-transmit-interval":300,
|
||||
"remote-echo-interval":50
|
||||
}
|
||||
]
|
||||
14
tests/topotests/bfd-bgp-cbit-topo3/r3/peers_down.json
Normal file
14
tests/topotests/bfd-bgp-cbit-topo3/r3/peers_down.json
Normal file
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"multihop":true,
|
||||
"peer":"2001:db8:1::1",
|
||||
"local":"2001:db8:4::1",
|
||||
"status":"down",
|
||||
"receive-interval":300,
|
||||
"transmit-interval":300,
|
||||
"echo-interval":0,
|
||||
"remote-receive-interval":300,
|
||||
"remote-transmit-interval":300,
|
||||
"remote-echo-interval":50
|
||||
}
|
||||
]
|
||||
7
tests/topotests/bfd-bgp-cbit-topo3/r3/zebra.conf
Normal file
7
tests/topotests/bfd-bgp-cbit-topo3/r3/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
||||
interface lo
|
||||
ip address 10.254.254.3/32
|
||||
!
|
||||
interface r3-eth0
|
||||
ipv6 address 2001:db8:4::1/64
|
||||
!
|
||||
ipv6 route 2001:db8:1::/64 2001:db8:4::2
|
||||
@ -0,0 +1,58 @@
|
||||
## Color coding:
|
||||
#########################
|
||||
## Main FRR: #f08080 red
|
||||
## Switches: #d0e0d0 gray
|
||||
## RIP: #19e3d9 Cyan
|
||||
## RIPng: #fcb314 dark yellow
|
||||
## OSPFv2: #32b835 Green
|
||||
## OSPFv3: #19e3d9 Cyan
|
||||
## ISIS IPv4 #fcb314 dark yellow
|
||||
## ISIS IPv6 #9a81ec purple
|
||||
## BGP IPv4 #eee3d3 beige
|
||||
## BGP IPv6 #fdff00 yellow
|
||||
##### Colors (see http://www.color-hex.com/)
|
||||
|
||||
graph template {
|
||||
label="bfd-topo2";
|
||||
|
||||
# Routers
|
||||
r1 [
|
||||
shape=doubleoctagon,
|
||||
label="r1",
|
||||
fillcolor="#f08080",
|
||||
style=filled,
|
||||
];
|
||||
r2 [
|
||||
shape=doubleoctagon
|
||||
label="r2",
|
||||
fillcolor="#f08080",
|
||||
style=filled,
|
||||
];
|
||||
r3 [
|
||||
shape=doubleoctagon
|
||||
label="r4",
|
||||
fillcolor="#f08080",
|
||||
style=filled,
|
||||
];
|
||||
|
||||
# Switches
|
||||
sw1 [
|
||||
shape=oval,
|
||||
label="sw1\n2001:db8:1::/64",
|
||||
fillcolor="#d0e0d0",
|
||||
style=filled,
|
||||
];
|
||||
sw2 [
|
||||
shape=oval,
|
||||
label="sw2\n10.0.3.0/24",
|
||||
fillcolor="#d0e0d0",
|
||||
style=filled,
|
||||
];
|
||||
|
||||
# Connections
|
||||
r1 -- sw1 [label="eth0"];
|
||||
r2 -- sw1 [label="eth0"];
|
||||
|
||||
r2 -- sw2 [label="eth1"];
|
||||
r3 -- sw2 [label="eth0"];
|
||||
}
|
||||
248
tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py
Executable file
248
tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py
Executable file
@ -0,0 +1,248 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# test_bfd_bgp_cbit_topo3.py
|
||||
#
|
||||
# Copyright (c) 2019 6WIND
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
"""
|
||||
test_bfd_bgp_cbit_topo3.py: Test the FRR/Quagga BFD daemon with multihop and BGP
|
||||
unnumbered.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
from functools import partial
|
||||
import pytest
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, '../'))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from lib import topotest
|
||||
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||
from lib.topolog import logger
|
||||
|
||||
# Required to instantiate the topology builder class.
|
||||
from mininet.topo import Topo
|
||||
|
||||
class BFDTopo(Topo):
|
||||
"Test topology builder"
|
||||
def build(self, *_args, **_opts):
|
||||
"Build function"
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Create 4 routers.
|
||||
for routern in range(1, 4):
|
||||
tgen.add_router('r{}'.format(routern))
|
||||
|
||||
switch = tgen.add_switch('s1')
|
||||
switch.add_link(tgen.gears['r1'])
|
||||
switch.add_link(tgen.gears['r2'])
|
||||
|
||||
switch = tgen.add_switch('s2')
|
||||
switch.add_link(tgen.gears['r2'])
|
||||
switch.add_link(tgen.gears['r3'])
|
||||
|
||||
def setup_module(mod):
|
||||
"Sets up the pytest environment"
|
||||
tgen = Topogen(BFDTopo, mod.__name__)
|
||||
tgen.start_topology()
|
||||
|
||||
router_list = tgen.routers()
|
||||
|
||||
for rname, router in router_list.iteritems():
|
||||
router.load_config(
|
||||
TopoRouter.RD_ZEBRA,
|
||||
os.path.join(CWD, '{}/zebra.conf'.format(rname)),
|
||||
)
|
||||
router.load_config(
|
||||
TopoRouter.RD_BFD,
|
||||
os.path.join(CWD, '{}/bfdd.conf'.format(rname))
|
||||
)
|
||||
router.load_config(
|
||||
TopoRouter.RD_BGP,
|
||||
os.path.join(CWD, '{}/bgpd.conf'.format(rname))
|
||||
)
|
||||
|
||||
# Initialize all routers.
|
||||
tgen.start_router()
|
||||
|
||||
# Verify that we are using the proper version and that the BFD
|
||||
# daemon exists.
|
||||
for router in router_list.values():
|
||||
# Check for Version
|
||||
if router.has_version('<', '5.1'):
|
||||
tgen.set_error('Unsupported FRR version')
|
||||
break
|
||||
|
||||
def teardown_module(_mod):
|
||||
"Teardown the pytest environment"
|
||||
tgen = get_topogen()
|
||||
tgen.stop_topology()
|
||||
|
||||
|
||||
def test_protocols_convergence():
|
||||
"""
|
||||
Assert that all protocols have converged before checking for the BFD
|
||||
statuses as they depend on it.
|
||||
"""
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
# Check IPv6 routing tables.
|
||||
logger.info("Checking IPv6 routes for convergence")
|
||||
for router in tgen.routers().values():
|
||||
if router.name == 'r2':
|
||||
continue
|
||||
json_file = '{}/{}/ipv6_routes.json'.format(CWD, router.name)
|
||||
if not os.path.isfile(json_file):
|
||||
logger.info('skipping file {}'.format(json_file))
|
||||
continue
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
router, 'show ipv6 route json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=40,
|
||||
wait=0.5)
|
||||
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_bfd_connection():
|
||||
"Assert that the BFD peers can find themselves."
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
logger.info('waiting for bfd peers to go up')
|
||||
for router in tgen.routers().values():
|
||||
if router.name == 'r2':
|
||||
continue
|
||||
json_file = '{}/{}/peers.json'.format(CWD, router.name)
|
||||
expected = json.loads(open(json_file).read())
|
||||
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
router, 'show bfd peers json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
|
||||
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||
assert result is None, assertmsg
|
||||
|
||||
def test_bfd_loss_intermediate():
|
||||
"""
|
||||
Assert that BFD notices the bfd link down failure.
|
||||
but BGP entries should still be present
|
||||
"""
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
logger.info('removing IPv6 address from r2 to simulate loss of connectivity')
|
||||
# Disable r2-eth0 ipv6 address
|
||||
cmd = 'vtysh -c \"configure terminal\" -c \"interface r2-eth1\" -c "no ipv6 address 2001:db8:4::2/64\"'
|
||||
tgen.net['r2'].cmd(cmd)
|
||||
|
||||
# Wait the minimum time we can before checking that BGP/BFD
|
||||
# converged.
|
||||
logger.info('waiting for BFD converge down')
|
||||
|
||||
# Check that BGP converged quickly.
|
||||
for router in tgen.routers().values():
|
||||
if router.name == 'r2':
|
||||
continue
|
||||
json_file = '{}/{}/peers_down.json'.format(CWD, router.name)
|
||||
expected = json.loads(open(json_file).read())
|
||||
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
router, 'show bfd peers json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
|
||||
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||
assert result is None, assertmsg
|
||||
|
||||
logger.info('waiting for BGP entries to become stale')
|
||||
for router in tgen.routers().values():
|
||||
if router.name == 'r2':
|
||||
continue
|
||||
json_file = '{}/{}/bgp_ipv6_routes_down.json'.format(CWD, router.name)
|
||||
expected = json.loads(open(json_file).read())
|
||||
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
router, 'show bgp ipv6 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=1)
|
||||
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||
assert result is None, assertmsg
|
||||
|
||||
logger.info("Checking IPv6 routes on r1 should still be present")
|
||||
for router in tgen.routers().values():
|
||||
if router.name == 'r2':
|
||||
continue
|
||||
if router.name == 'r3':
|
||||
continue
|
||||
json_file = '{}/r1/ipv6_routes.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
router, 'show ipv6 route json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=30,
|
||||
wait=0.5)
|
||||
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||
assert result is None, assertmsg
|
||||
|
||||
def test_bfd_comes_back_again():
|
||||
"""
|
||||
Assert that BFD notices the bfd link up
|
||||
and that ipv6 entries appear back
|
||||
"""
|
||||
tgen = get_topogen()
|
||||
logger.info('re-adding IPv6 address from r2 to simulate connectivity is back')
|
||||
# adds back r2-eth0 ipv6 address
|
||||
cmd = 'vtysh -c \"configure terminal\" -c \"interface r2-eth1\" -c "ipv6 address 2001:db8:4::2/64\"'
|
||||
tgen.net['r2'].cmd(cmd)
|
||||
|
||||
# Wait the minimum time we can before checking that BGP/BFD
|
||||
# converged.
|
||||
logger.info('waiting for BFD to converge up')
|
||||
|
||||
# Check that BGP converged quickly.
|
||||
for router in tgen.routers().values():
|
||||
if router.name == 'r2':
|
||||
continue
|
||||
json_file = '{}/{}/peers.json'.format(CWD, router.name)
|
||||
expected = json.loads(open(json_file).read())
|
||||
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
router, 'show bfd peers json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
|
||||
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_memory_leak():
|
||||
"Run the memory leak test and report results."
|
||||
tgen = get_topogen()
|
||||
if not tgen.is_memleak_enabled():
|
||||
pytest.skip('Memory leak test/report is disabled')
|
||||
|
||||
tgen.report_memory_leaks()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
||||
@ -93,6 +93,7 @@ const char ZEBRA_PTM_BFD_IFNAME_FIELD[] = "ifName";
|
||||
const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD[] = "maxHopCnt";
|
||||
const char ZEBRA_PTM_BFD_SEND_EVENT[] = "sendEvent";
|
||||
const char ZEBRA_PTM_BFD_VRF_NAME_FIELD[] = "vrfName";
|
||||
const char ZEBRA_PTM_BFD_CBIT_FIELD[] = "bfdcbit";
|
||||
|
||||
static ptm_lib_handle_t *ptm_hdl;
|
||||
|
||||
@ -688,6 +689,7 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
|
||||
char tmp_buf[64];
|
||||
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
|
||||
unsigned int pid;
|
||||
uint8_t cbit_set;
|
||||
|
||||
if (hdr->command == ZEBRA_BFD_DEST_UPDATE)
|
||||
client->bfd_peer_upd8_cnt++;
|
||||
@ -813,6 +815,10 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
|
||||
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
||||
ZEBRA_PTM_BFD_IFNAME_FIELD, if_name);
|
||||
}
|
||||
STREAM_GETC(s, cbit_set);
|
||||
sprintf(tmp_buf, "%d", cbit_set);
|
||||
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
||||
ZEBRA_PTM_BFD_CBIT_FIELD, tmp_buf);
|
||||
|
||||
sprintf(tmp_buf, "%d", 1);
|
||||
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user