Skip to content

Commit

Permalink
Add bfd session params to dest register msg
Browse files Browse the repository at this point in the history
Allow protocols to create bfd session ids and control
the bfd session status and configure it in frr-bfd via
the ZEBRA_BFD_DEST_REGISTER message. This is 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.
  • Loading branch information
lokeshdh committed Nov 21, 2023
1 parent 83cbdcc commit b5709dc
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 1 deletion.
20 changes: 19 additions & 1 deletion bfdd/bfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,18 @@ 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 +899,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 +917,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
37 changes: 37 additions & 0 deletions bfdd/ptm_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,32 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
* - c: profile name length.
* - X bytes: profile name.
*
* New format (with session id and status):
* - header: Command, VRF
* - l: pid
* - w: family
* - AF_INET:
* - l: destination IPv4 address
* - AF_INET6:
* - 16 bytes: destination IPv6 address
* - l: min_rx
* - l: min_tx
* - c: detect multiplier
* - c: is_multihop?
* - w: family
* - AF_INET:
* - l: source IPv4 address
* - AF_INET6:
* - 16 bytes: source IPv6 address
* - c: ttl
* - c: ifname length
* - X bytes: interface name
* - 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 +469,12 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
bpc->bpc_profile[ifnamelen] = 0;
}

/* 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 +512,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

0 comments on commit b5709dc

Please sign in to comment.