mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 19:39:28 +00:00
bfdd: implement passive mode
The passive mode is briefly described in the RFC 5880 Bidirectional Forwarding Detection (BFD), Section 6.1. Overview: > A system may take either an Active role or a Passive role in session > initialization. A system taking the Active role MUST send BFD > Control packets for a particular session, regardless of whether it > has received any BFD packets for that session. A system taking the > Passive role MUST NOT begin sending BFD packets for a particular > session until it has received a BFD packet for that session, and thus > has learned the remote system's discriminator value. At least one > system MUST take the Active role (possibly both). The role that a > system takes is specific to the application of BFD, and is outside > the scope of this specification. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
parent
8733bc48ea
commit
1a2e2fff35
64
bfdd/bfd.c
64
bfdd/bfd.c
@ -88,6 +88,7 @@ static void bfd_profile_set_default(struct bfd_profile *bp)
|
||||
bp->admin_shutdown = true;
|
||||
bp->detection_multiplier = BFD_DEFDETECTMULT;
|
||||
bp->echo_mode = false;
|
||||
bp->passive = false;
|
||||
bp->min_echo_rx = BFD_DEF_REQ_MIN_ECHO;
|
||||
bp->min_rx = BFD_DEFREQUIREDMINRX;
|
||||
bp->min_tx = BFD_DEFDESIREDMINTX;
|
||||
@ -159,8 +160,10 @@ static void _bfd_profile_remove(struct bfd_session *bs, bool apply)
|
||||
bfd_set_echo(bs, bs->peer_profile.echo_mode);
|
||||
}
|
||||
|
||||
if (apply)
|
||||
if (apply) {
|
||||
bfd_set_passive_mode(bs, bs->peer_profile.passive);
|
||||
bfd_set_shutdown(bs, bs->peer_profile.admin_shutdown);
|
||||
}
|
||||
}
|
||||
|
||||
void bfd_profile_apply(const char *profname, struct bfd_session *bs)
|
||||
@ -221,6 +224,12 @@ void bfd_profile_apply(const char *profname, struct bfd_session *bs)
|
||||
bfd_set_echo(bs, bs->peer_profile.echo_mode);
|
||||
}
|
||||
|
||||
/* Toggle 'passive-mode' if default value. */
|
||||
if (bs->peer_profile.passive == false)
|
||||
bfd_set_passive_mode(bs, bp->passive);
|
||||
else
|
||||
bfd_set_passive_mode(bs, bs->peer_profile.passive);
|
||||
|
||||
/* Toggle 'no shutdown' if default value. */
|
||||
if (bs->peer_profile.admin_shutdown)
|
||||
bfd_set_shutdown(bs, bp->admin_shutdown);
|
||||
@ -374,8 +383,12 @@ int bfd_session_enable(struct bfd_session *bs)
|
||||
* protocol.
|
||||
*/
|
||||
bs->sock = psock;
|
||||
bfd_recvtimer_update(bs);
|
||||
ptm_bfd_start_xmt_timer(bs, false);
|
||||
|
||||
/* Only start timers if we are using active mode. */
|
||||
if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE) == 0) {
|
||||
bfd_recvtimer_update(bs);
|
||||
ptm_bfd_start_xmt_timer(bs, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -536,6 +549,12 @@ void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag)
|
||||
if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
|
||||
ptm_bfd_echo_stop(bfd);
|
||||
|
||||
/* Stop attempting to transmit or expect control packets if passive. */
|
||||
if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_PASSIVE)) {
|
||||
bfd_recvtimer_delete(bfd);
|
||||
bfd_xmttimer_delete(bfd);
|
||||
}
|
||||
|
||||
if (old_state != bfd->ses_state) {
|
||||
bfd->stats.session_down++;
|
||||
if (bglobal.debug_peer_event)
|
||||
@ -766,6 +785,7 @@ static void _bfd_session_update(struct bfd_session *bs,
|
||||
* the session is disabled.
|
||||
*/
|
||||
bs->peer_profile.admin_shutdown = bpc->bpc_shutdown;
|
||||
bfd_set_passive_mode(bs, bpc->bpc_passive);
|
||||
bfd_set_shutdown(bs, bpc->bpc_shutdown);
|
||||
|
||||
/*
|
||||
@ -986,6 +1006,10 @@ static void bs_down_handler(struct bfd_session *bs, int nstate)
|
||||
* bring it up.
|
||||
*/
|
||||
bs->ses_state = PTM_BFD_INIT;
|
||||
|
||||
/* Answer peer with INIT immediately in passive mode. */
|
||||
if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE))
|
||||
ptm_bfd_snd(bs, 0);
|
||||
break;
|
||||
|
||||
case PTM_BFD_INIT:
|
||||
@ -1312,9 +1336,39 @@ void bfd_set_shutdown(struct bfd_session *bs, bool shutdown)
|
||||
bs->ses_state = PTM_BFD_DOWN;
|
||||
control_notify(bs, bs->ses_state);
|
||||
|
||||
/* Enable all timers. */
|
||||
bfd_recvtimer_update(bs);
|
||||
/* Enable timers if non passive, otherwise stop them. */
|
||||
if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE)) {
|
||||
bfd_recvtimer_delete(bs);
|
||||
bfd_xmttimer_delete(bs);
|
||||
} else {
|
||||
bfd_recvtimer_update(bs);
|
||||
bfd_xmttimer_update(bs, bs->xmt_TO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bfd_set_passive_mode(struct bfd_session *bs, bool passive)
|
||||
{
|
||||
if (passive) {
|
||||
SET_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE);
|
||||
|
||||
/* Session is already up and running, nothing to do now. */
|
||||
if (bs->ses_state != PTM_BFD_DOWN)
|
||||
return;
|
||||
|
||||
/* Lets disable the timers since we are now passive. */
|
||||
bfd_recvtimer_delete(bs);
|
||||
bfd_xmttimer_delete(bs);
|
||||
} else {
|
||||
UNSET_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE);
|
||||
|
||||
/* Session is already up and running, nothing to do now. */
|
||||
if (bs->ses_state != PTM_BFD_DOWN)
|
||||
return;
|
||||
|
||||
/* Session is down, let it attempt to start the connection. */
|
||||
bfd_xmttimer_update(bs, bs->xmt_TO);
|
||||
bfd_recvtimer_update(bs);
|
||||
}
|
||||
}
|
||||
|
||||
|
11
bfdd/bfd.h
11
bfdd/bfd.h
@ -170,6 +170,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 */
|
||||
BFD_SESS_FLAG_PASSIVE = 1 << 10, /* Passive mode */
|
||||
};
|
||||
|
||||
/* BFD session hash keys */
|
||||
@ -207,6 +208,8 @@ struct bfd_profile {
|
||||
uint32_t min_rx;
|
||||
/** Administrative state. */
|
||||
bool admin_shutdown;
|
||||
/** Passive mode. */
|
||||
bool passive;
|
||||
|
||||
/** Echo mode (only applies to single hop). */
|
||||
bool echo_mode;
|
||||
@ -607,6 +610,14 @@ void bfd_set_echo(struct bfd_session *bs, bool echo);
|
||||
*/
|
||||
void bfd_set_shutdown(struct bfd_session *bs, bool shutdown);
|
||||
|
||||
/**
|
||||
* Set the BFD session passive mode.
|
||||
*
|
||||
* \param bs the BFD session.
|
||||
* \param passive the passive mode.
|
||||
*/
|
||||
void bfd_set_passive_mode(struct bfd_session *bs, bool passive);
|
||||
|
||||
/* BFD hash data structures interface */
|
||||
void bfd_initialize(void);
|
||||
void bfd_shutdown(void);
|
||||
|
@ -89,6 +89,7 @@ struct bfd_peer_cfg {
|
||||
bool bpc_shutdown;
|
||||
|
||||
bool bpc_cbit;
|
||||
bool bpc_passive;
|
||||
|
||||
bool bpc_has_profile;
|
||||
char bpc_profile[64];
|
||||
|
@ -265,6 +265,27 @@ void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
|
||||
yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
|
||||
}
|
||||
|
||||
DEFPY_YANG(
|
||||
bfd_peer_passive, bfd_peer_passive_cmd,
|
||||
"[no] passive-mode",
|
||||
NO_STR
|
||||
"Don't attempt to start sessions\n")
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./passive-mode", NB_OP_MODIFY,
|
||||
no ? "false" : "true");
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
void bfd_cli_show_passive(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults)
|
||||
{
|
||||
if (show_defaults)
|
||||
vty_out(vty, " no passive-mode\n");
|
||||
else
|
||||
vty_out(vty, " %spassive-mode\n",
|
||||
yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
|
||||
}
|
||||
|
||||
DEFPY_YANG(
|
||||
bfd_peer_mult, bfd_peer_mult_cmd,
|
||||
"detect-multiplier (2-255)$multiplier",
|
||||
@ -462,6 +483,11 @@ ALIAS_YANG(bfd_peer_shutdown, bfd_profile_shutdown_cmd,
|
||||
NO_STR
|
||||
"Disable BFD peer\n")
|
||||
|
||||
ALIAS_YANG(bfd_peer_passive, bfd_profile_passive_cmd,
|
||||
"[no] passive-mode",
|
||||
NO_STR
|
||||
"Don't attempt to start sessions\n")
|
||||
|
||||
ALIAS_YANG(bfd_peer_echo, bfd_profile_echo_cmd,
|
||||
"[no] echo-mode",
|
||||
NO_STR
|
||||
@ -530,6 +556,7 @@ bfdd_cli_init(void)
|
||||
install_element(BFD_PEER_NODE, &bfd_peer_echo_cmd);
|
||||
install_element(BFD_PEER_NODE, &bfd_peer_echo_interval_cmd);
|
||||
install_element(BFD_PEER_NODE, &bfd_peer_profile_cmd);
|
||||
install_element(BFD_PEER_NODE, &bfd_peer_passive_cmd);
|
||||
|
||||
/* Profile commands. */
|
||||
cmd_variable_handler_register(bfd_vars);
|
||||
@ -546,4 +573,5 @@ bfdd_cli_init(void)
|
||||
install_element(BFD_PROFILE_NODE, &bfd_profile_shutdown_cmd);
|
||||
install_element(BFD_PROFILE_NODE, &bfd_profile_echo_cmd);
|
||||
install_element(BFD_PROFILE_NODE, &bfd_profile_echo_interval_cmd);
|
||||
install_element(BFD_PROFILE_NODE, &bfd_profile_passive_cmd);
|
||||
}
|
||||
|
@ -77,6 +77,13 @@ const struct frr_yang_module_info frr_bfdd_info = {
|
||||
.cli_show = bfd_cli_show_shutdown,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-bfdd:bfdd/bfd/profile/passive-mode",
|
||||
.cbs = {
|
||||
.modify = bfdd_bfd_profile_passive_mode_modify,
|
||||
.cli_show = bfd_cli_show_passive,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-bfdd:bfdd/bfd/profile/echo-mode",
|
||||
.cbs = {
|
||||
@ -146,6 +153,13 @@ const struct frr_yang_module_info frr_bfdd_info = {
|
||||
.cli_show = bfd_cli_show_shutdown,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode",
|
||||
.cbs = {
|
||||
.modify = bfdd_bfd_sessions_single_hop_passive_mode_modify,
|
||||
.cli_show = bfd_cli_show_passive,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode",
|
||||
.cbs = {
|
||||
@ -328,6 +342,13 @@ const struct frr_yang_module_info frr_bfdd_info = {
|
||||
.cli_show = bfd_cli_show_shutdown,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/passive-mode",
|
||||
.cbs = {
|
||||
.modify = bfdd_bfd_sessions_single_hop_passive_mode_modify,
|
||||
.cli_show = bfd_cli_show_passive,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-discriminator",
|
||||
.cbs = {
|
||||
|
@ -37,6 +37,7 @@ int bfdd_bfd_profile_desired_transmission_interval_modify(
|
||||
int bfdd_bfd_profile_required_receive_interval_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args);
|
||||
int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args);
|
||||
int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args *args);
|
||||
int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
@ -62,6 +63,8 @@ int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int bfdd_bfd_sessions_single_hop_administrative_down_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int bfdd_bfd_sessions_single_hop_passive_mode_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int bfdd_bfd_sessions_single_hop_echo_mode_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
|
||||
@ -206,5 +209,7 @@ void bfd_cli_show_profile(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void bfd_cli_peer_profile_show(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void bfd_cli_show_passive(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
|
||||
#endif /* _FRR_BFDD_NB_H_ */
|
||||
|
@ -359,6 +359,28 @@ int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-bfdd:bfdd/bfd/profile/passive-mode
|
||||
*/
|
||||
int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct bfd_profile *bp;
|
||||
bool passive;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
passive = yang_dnode_get_bool(args->dnode, NULL);
|
||||
bp = nb_running_get_entry(args->dnode, NULL, true);
|
||||
if (bp->passive == passive)
|
||||
return NB_OK;
|
||||
|
||||
bp->passive = passive;
|
||||
bfd_profile_update(bp);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-bfdd:bfdd/bfd/profile/echo-mode
|
||||
*/
|
||||
@ -611,6 +633,36 @@ int bfdd_bfd_sessions_single_hop_administrative_down_modify(
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/passive-mode
|
||||
*/
|
||||
int bfdd_bfd_sessions_single_hop_passive_mode_modify(
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct bfd_session *bs;
|
||||
bool passive;
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
return NB_OK;
|
||||
|
||||
case NB_EV_APPLY:
|
||||
break;
|
||||
|
||||
case NB_EV_ABORT:
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
passive = yang_dnode_get_bool(args->dnode, NULL);
|
||||
|
||||
bs = nb_running_get_entry(args->dnode, NULL, true);
|
||||
bs->peer_profile.passive = passive;
|
||||
bfd_set_passive_mode(bs, passive);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
|
||||
*/
|
||||
|
@ -111,6 +111,10 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
|
||||
|
||||
vty_out(vty, "\t\tID: %u\n", bs->discrs.my_discr);
|
||||
vty_out(vty, "\t\tRemote ID: %u\n", bs->discrs.remote_discr);
|
||||
if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE))
|
||||
vty_out(vty, "\t\tPassive mode\n");
|
||||
else
|
||||
vty_out(vty, "\t\tActive mode\n");
|
||||
|
||||
vty_out(vty, "\t\tStatus: ");
|
||||
switch (bs->ses_state) {
|
||||
@ -203,6 +207,8 @@ static struct json_object *__display_peer_json(struct bfd_session *bs)
|
||||
|
||||
json_object_int_add(jo, "id", bs->discrs.my_discr);
|
||||
json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
|
||||
json_object_boolean_add(jo, "passive-mode",
|
||||
CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE));
|
||||
|
||||
switch (bs->ses_state) {
|
||||
case PTM_BFD_ADM_DOWN:
|
||||
|
Loading…
Reference in New Issue
Block a user