summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfd.c11
-rw-r--r--bfdd/bfd.h8
-rw-r--r--bfdd/bfd_packet.c9
-rw-r--r--bfdd/bfdctl.h2
-rw-r--r--bfdd/ptm_adapter.c13
-rw-r--r--bgpd/bgp_bfd.c44
-rw-r--r--isisd/isis_bfd.c5
-rw-r--r--lib/bfd.c14
-rw-r--r--lib/bfd.h6
-rw-r--r--ospf6d/ospf6_bfd.c10
-rw-r--r--ospfd/ospf_bfd.c8
-rw-r--r--pimd/pim_bfd.c10
-rw-r--r--zebra/zebra_ptm.c6
13 files changed, 121 insertions, 25 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index a2e84e928d..d4e2834835 100644
--- a/bfdd/bfd.c
+++ b/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)
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 3f3d603832..213e905bf0 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -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;
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 8edba05d12..f3acfa4167 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -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));
diff --git a/bfdd/bfdctl.h b/bfdd/bfdctl.h
index 0da1ca8df6..4ce23a8f27 100644
--- a/bfdd/bfdctl.h
+++ b/bfdd/bfdctl.h
@@ -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;
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index a12a3c196b..3e2ace6ea6 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -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
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index a9c30acafb..cf17250931 100644
--- a/bgpd/bgp_bfd.c
+++ b/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,28 @@ 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 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))
+ 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 +268,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 +289,13 @@ 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) &&
+ !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 +319,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 +371,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 +402,8 @@ static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS)
continue;
bgp_bfd_peer_status_update(peer,
- status);
+ status,
+ remote_cbit);
}
}
}
diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c
index fccef0169e..fa89c80049 100644
--- a/isisd/isis_bfd.c
+++ b/isisd/isis_bfd.c
@@ -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);
diff --git a/lib/bfd.c b/lib/bfd.c
index a8956c315c..00dbd1b3d1 100644
--- a/lib/bfd.c
+++ b/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;
}
diff --git a/lib/bfd.h b/lib/bfd.h
index d02110a997..7f376a2470 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -48,6 +48,7 @@ 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_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */
#define BFD_STATUS_DOWN (1 << 1) /* BFD session status is down */
@@ -83,13 +84,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);
diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c
index 7a26af1f09..f0500601b0 100644
--- a/ospf6d/ospf6_bfd.c
+++ b/ospf6d/ospf6_bfd.c
@@ -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;
diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c
index c8ad6d04f4..a17975270a 100644
--- a/ospfd/ospf_bfd.c
+++ b/ospfd/ospf_bfd.c
@@ -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;
diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c
index 300261e5a9..87d0f9fa22 100644
--- a/pimd/pim_bfd.c
+++ b/pimd/pim_bfd.c
@@ -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;
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index d3ecd3695a..46f1385520 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -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,