summaryrefslogtreecommitdiff
path: root/bfdd/bfd.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfdd/bfd.c')
-rw-r--r--bfdd/bfd.c161
1 files changed, 101 insertions, 60 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 7d6f4c1431..c16912060c 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -88,6 +88,8 @@ 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->minimum_ttl = BFD_DEF_MHOP_TTL;
bp->min_echo_rx = BFD_DEF_REQ_MIN_ECHO;
bp->min_rx = BFD_DEFREQUIREDMINRX;
bp->min_tx = BFD_DEFDESIREDMINTX;
@@ -124,53 +126,12 @@ void bfd_profile_free(struct bfd_profile *bp)
XFREE(MTYPE_BFDD_PROFILE, bp);
}
-/**
- * Removes a profile and tests whether it needs to apply the changes or not.
- *
- * \param bs the BFD session.
- * \param apply whether or not to apply configurations immediately.
- */
-static void _bfd_profile_remove(struct bfd_session *bs, bool apply)
-{
- struct bfd_profile *bp;
-
- /* No profile applied, nothing to do. */
- bp = bs->profile;
- if (bp == NULL)
- return;
-
- /* Remove the profile association. */
- bs->profile = NULL;
-
- /* Set multiplier to the default. */
- bs->detect_mult = bs->peer_profile.detection_multiplier;
-
- /* Set timers back to user configuration. */
- bs->timers.desired_min_tx = bs->peer_profile.min_tx;
- bs->timers.required_min_rx = bs->peer_profile.min_rx;
-
- /* We can only apply echo options on single hop sessions. */
- if (!CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
- /* Set default echo timer. */
- bs->timers.required_min_echo = bs->peer_profile.min_echo_rx;
-
- /* Default is no echo mode. */
- if (apply)
- bfd_set_echo(bs, bs->peer_profile.echo_mode);
- }
-
- if (apply)
- bfd_set_shutdown(bs, bs->peer_profile.admin_shutdown);
-}
-
void bfd_profile_apply(const char *profname, struct bfd_session *bs)
{
struct bfd_profile *bp;
/* Remove previous profile if any. */
if (bs->profile_name) {
- _bfd_profile_remove(bs, false);
-
/* We are changing profiles. */
if (strcmp(bs->profile_name, profname)) {
XFREE(MTYPE_BFDD_PROFILE, bs->profile_name);
@@ -182,12 +143,23 @@ void bfd_profile_apply(const char *profname, struct bfd_session *bs)
/* Look up new profile to apply. */
bp = bfd_profile_lookup(profname);
- if (bp == NULL)
- return;
/* Point to profile if it exists. */
bs->profile = bp;
+ /* Apply configuration. */
+ bfd_session_apply(bs);
+}
+
+void bfd_session_apply(struct bfd_session *bs)
+{
+ struct bfd_profile *bp;
+ uint32_t min_tx = bs->timers.desired_min_tx;
+ uint32_t min_rx = bs->timers.required_min_rx;
+
+ /* Pick the source of configuration. */
+ bp = bs->profile ? bs->profile : &bs->peer_profile;
+
/* Set multiplier if not the default. */
if (bs->peer_profile.detection_multiplier == BFD_DEFDETECTMULT)
bs->detect_mult = bp->detection_multiplier;
@@ -219,21 +191,40 @@ void bfd_profile_apply(const char *profname, struct bfd_session *bs)
bfd_set_echo(bs, bp->echo_mode);
else
bfd_set_echo(bs, bs->peer_profile.echo_mode);
+ } else {
+ /* Configure the TTL packet filter. */
+ if (bs->peer_profile.minimum_ttl == BFD_DEF_MHOP_TTL)
+ bs->mh_ttl = bp->minimum_ttl;
+ else
+ bs->mh_ttl = bs->peer_profile.minimum_ttl;
}
+ /* 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);
else
bfd_set_shutdown(bs, bs->peer_profile.admin_shutdown);
+
+ /* If session interval changed negotiate new timers. */
+ if (bs->ses_state == PTM_BFD_UP
+ && (bs->timers.desired_min_tx != min_tx
+ || bs->timers.required_min_rx != min_rx))
+ bfd_set_polling(bs);
}
void bfd_profile_remove(struct bfd_session *bs)
{
/* Remove any previous set profile name. */
XFREE(MTYPE_BFDD_PROFILE, bs->profile_name);
+ bs->profile = NULL;
- _bfd_profile_remove(bs, true);
+ bfd_session_apply(bs);
}
void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
@@ -374,8 +365,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 +531,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)
@@ -758,6 +759,11 @@ static void _bfd_session_update(struct bfd_session *bs,
else
UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CBIT);
+ if (bpc->bpc_has_minimum_ttl) {
+ bs->mh_ttl = bpc->bpc_minimum_ttl;
+ bs->peer_profile.minimum_ttl = bpc->bpc_minimum_ttl;
+ }
+
bs->peer_profile.echo_mode = bpc->bpc_echo;
bfd_set_echo(bs, bpc->bpc_echo);
@@ -766,6 +772,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);
/*
@@ -924,8 +931,7 @@ int ptm_bfd_sess_del(struct bfd_peer_cfg *bpc)
/* This pointer is being referenced, don't let it be deleted. */
if (bs->refcount > 0) {
- zlog_err("session-delete: refcount failure: %" PRIu64
- " references",
+ zlog_err("session-delete: refcount failure: %" PRIu64" references",
bs->refcount);
return -1;
}
@@ -987,6 +993,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:
@@ -1313,9 +1323,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);
}
}
@@ -1693,8 +1733,7 @@ struct bfd_session *bfd_key_lookup(struct bfd_key key)
inet_ntop(bs.key.family, &bs.key.local,
addr_buf, sizeof(addr_buf));
zlog_debug(
- " peer %s found, but ifp %s"
- " and loc-addr %s ignored",
+ " peer %s found, but ifp %s and loc-addr %s ignored",
peer_buf, key.ifname, addr_buf);
}
return bsp;
@@ -1716,8 +1755,7 @@ struct bfd_session *bfd_key_lookup(struct bfd_key key)
bsp = ctx.result;
if (bglobal.debug_peer_event)
zlog_debug(
- " peer %s found, but ifp"
- " and/or loc-addr params ignored",
+ " peer %s found, but ifp and/or loc-addr params ignored",
peer_buf);
}
return bsp;
@@ -2014,16 +2052,16 @@ static int bfd_vrf_enable(struct vrf *vrf)
if (!bvrf->bg_ev[1])
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,
&bvrf->bg_ev[1]);
- if (!bvrf->bg_ev[2])
+ if (!bvrf->bg_ev[2] && bvrf->bg_shop6 != -1)
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,
&bvrf->bg_ev[2]);
- if (!bvrf->bg_ev[3])
+ if (!bvrf->bg_ev[3] && bvrf->bg_mhop6 != -1)
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
&bvrf->bg_ev[3]);
if (!bvrf->bg_ev[4])
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo,
&bvrf->bg_ev[4]);
- if (!bvrf->bg_ev[5])
+ if (!bvrf->bg_ev[5] && bvrf->bg_echov6 != -1)
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
&bvrf->bg_ev[5]);
}
@@ -2062,10 +2100,13 @@ static int bfd_vrf_disable(struct vrf *vrf)
socket_close(&bvrf->bg_echo);
socket_close(&bvrf->bg_shop);
socket_close(&bvrf->bg_mhop);
- socket_close(&bvrf->bg_shop6);
- socket_close(&bvrf->bg_mhop6);
+ if (bvrf->bg_shop6 != -1)
+ socket_close(&bvrf->bg_shop6);
+ if (bvrf->bg_mhop6 != -1)
+ socket_close(&bvrf->bg_mhop6);
socket_close(&bvrf->bg_echo);
- socket_close(&bvrf->bg_echov6);
+ if (bvrf->bg_echov6 != -1)
+ socket_close(&bvrf->bg_echov6);
/* free context */
XFREE(MTYPE_BFDD_VRF, bvrf);