Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion bfdd/bfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,19 @@ int bfd_session_enable(struct bfd_session *bs)
if (bs->bdc)
return 0;

/* Wait for the session to be enabled. We keep the session in INIT state
* to avoid triggering a DOWN event on the remote end if the session
* was UP earlier. This is particularly useful in case of "Stacking" when
* the Active(session enabled) and Standby(session disabled) switches run
* the same BFD session and if the Active fails and the Standby becomes
* Active but the session remains UP without affecting the routing protocols
* with the DOWN event.
*/
if (bs->ses_disable) {
bs->ses_state = PTM_BFD_INIT;
return 0;
}

/*
* If the interface or VRF doesn't exist, then we must register
* the session but delay its start.
Expand Down Expand Up @@ -887,6 +900,11 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)

bfd->key.mhop = bpc->bpc_mhop;

/* Get the protocol instructions to disable the bfd session */
bfd->ses_disable = bpc->bpc_session_disable;

/* Get the session id(my discriminator) from the protocol */
bfd->session_id = bpc->bpc_session_id;
if (bs_registrate(bfd) == NULL)
return NULL;

Expand All @@ -900,7 +918,8 @@ struct bfd_session *bs_registrate(struct bfd_session *bfd)
{
/* Registrate session into data structures. */
bfd_key_insert(bfd);
bfd->discrs.my_discr = ptm_bfd_gen_ID();
/* If the session id is generated by the protocol then use it, otherwise generate one */
bfd->discrs.my_discr = bfd->session_id ? bfd->session_id : ptm_bfd_gen_ID();
bfd_id_insert(bfd);

/* Try to enable session and schedule for packet receive/send. */
Expand Down
4 changes: 4 additions & 0 deletions bfdd/bfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ struct bfd_config_timers {
*/
struct bfd_session {

/* protocol parameters */
bool ses_disable;
uint32_t session_id;

/* protocol state per RFC 5880*/
uint8_t ses_state;
struct bfd_discrs discrs;
Expand Down
4 changes: 4 additions & 0 deletions bfdd/bfdctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ struct bfd_peer_cfg {
bool bpc_has_profile;
char bpc_profile[64];

/* protocol parameters */
uint32_t bpc_session_id;
bool bpc_session_disable;

/* Status information */
enum bfd_peer_status bpc_bps;
uint32_t bpc_id;
Expand Down
15 changes: 15 additions & 0 deletions bfdd/ptm_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,8 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
* - c: bfd_cbit
* - c: profile name length.
* - X bytes: profile name.
* - l: session id
* - c: session disabled?
*
* q(64), l(32), w(16), c(8)
*/
Expand Down Expand Up @@ -443,6 +445,14 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
bpc->bpc_profile[ifnamelen] = 0;
}

if (STREAM_READABLE (msg)) {
/* Get the session id */
STREAM_GETL(msg, bpc->bpc_session_id);

/* Get the session disable state. */
STREAM_GETC(msg, bpc->bpc_session_disable);
}

/* Sanity check: peer and local address must match IP types. */
if (bpc->bpc_local.sa_sin.sin_family != AF_UNSPEC
&& (bpc->bpc_local.sa_sin.sin_family
Expand Down Expand Up @@ -480,6 +490,11 @@ static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id)
return;
}
} else {
/* Existing BFD session has been enabled */
if (!bpc.bpc_session_disable && bpc.bpc_session_disable != bs->ses_disable) {
bs->ses_disable = bpc.bpc_session_disable;
bfd_session_enable(bs);
}
/*
* BFD session was already created, we are just updating the
* current peer.
Expand Down