summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfd.c64
-rw-r--r--bfdd/bfd.h11
-rw-r--r--bfdd/bfdctl.h1
-rw-r--r--bfdd/bfdd_cli.c28
-rw-r--r--bfdd/bfdd_nb.c21
-rw-r--r--bfdd/bfdd_nb.h5
-rw-r--r--bfdd/bfdd_nb_config.c52
-rw-r--r--bfdd/bfdd_vty.c6
8 files changed, 183 insertions, 5 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index caa80ed51d..1d50d98c78 100644
--- a/bfdd/bfd.c
+++ b/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);
}
}
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 492334a670..88ca17a9a9 100644
--- a/bfdd/bfd.h
+++ b/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);
diff --git a/bfdd/bfdctl.h b/bfdd/bfdctl.h
index 95cfcb1105..3cb2fba49a 100644
--- a/bfdd/bfdctl.h
+++ b/bfdd/bfdctl.h
@@ -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];
diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c
index 0dd021d475..e70354de05 100644
--- a/bfdd/bfdd_cli.c
+++ b/bfdd/bfdd_cli.c
@@ -266,6 +266,27 @@ void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
}
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",
"Configure peer detection multiplier\n"
@@ -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);
}
diff --git a/bfdd/bfdd_nb.c b/bfdd/bfdd_nb.c
index 2ff99ca608..cf063f82fc 100644
--- a/bfdd/bfdd_nb.c
+++ b/bfdd/bfdd_nb.c
@@ -78,6 +78,13 @@ const struct frr_yang_module_info frr_bfdd_info = {
}
},
{
+ .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 = {
.modify = bfdd_bfd_profile_echo_mode_modify,
@@ -147,6 +154,13 @@ const struct frr_yang_module_info frr_bfdd_info = {
}
},
{
+ .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 = {
.modify = bfdd_bfd_sessions_single_hop_echo_mode_modify,
@@ -329,6 +343,13 @@ const struct frr_yang_module_info frr_bfdd_info = {
}
},
{
+ .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 = {
.get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem,
diff --git a/bfdd/bfdd_nb.h b/bfdd/bfdd_nb.h
index a379c2135e..ec467f357f 100644
--- a/bfdd/bfdd_nb.h
+++ b/bfdd/bfdd_nb.h
@@ -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_ */
diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c
index 970b5f2d65..d50f746d3d 100644
--- a/bfdd/bfdd_nb_config.c
+++ b/bfdd/bfdd_nb_config.c
@@ -360,6 +360,28 @@ int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
}
/*
+ * 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
*/
int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args *args)
@@ -612,6 +634,36 @@ int bfdd_bfd_sessions_single_hop_administrative_down_modify(
}
/*
+ * 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
*/
int bfdd_bfd_sessions_single_hop_echo_mode_modify(
diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c
index 8318ea9665..a532b76f0e 100644
--- a/bfdd/bfdd_vty.c
+++ b/bfdd/bfdd_vty.c
@@ -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: