summaryrefslogtreecommitdiffstats
path: root/bfdd
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2020-06-16 13:56:03 +0200
committerGitHub <noreply@github.com>2020-06-16 13:56:03 +0200
commitcba183561b53b3562ec7c4dd23115b02efc26e22 (patch)
treec20fdad7fb77e84d000868b83de74cd7d8f85369 /bfdd
parentMerge pull request #6575 from mjstapp/fix_avoid_clang_add_fetch (diff)
parentbfdd: tell peer when our control plane is dead (diff)
downloadfrr-cba183561b53b3562ec7c4dd23115b02efc26e22.tar.xz
frr-cba183561b53b3562ec7c4dd23115b02efc26e22.zip
Merge pull request #6390 from opensourcerouting/bfd-cp-fix
bfdd: tell peer when our control plane is dead
Diffstat (limited to 'bfdd')
-rw-r--r--bfdd/ptm_adapter.c63
1 files changed, 51 insertions, 12 deletions
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 25938dd9f..ed6db2411 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -128,6 +128,35 @@ static void debug_printbpc(const struct bfd_peer_cfg *bpc, const char *fmt, ...)
timers[0], timers[1], timers[2], cbit_str);
}
+static void _ptm_bfd_session_del(struct bfd_session *bs, uint8_t diag)
+{
+ if (bglobal.debug_peer_event)
+ zlog_debug("session-delete: %s", bs_to_string(bs));
+
+ /* Change state and notify peer. */
+ bs->ses_state = PTM_BFD_DOWN;
+ bs->local_diag = diag;
+ ptm_bfd_snd(bs, 0);
+
+ /* Session reached refcount == 0, lets delete it. */
+ if (bs->refcount == 0) {
+ /*
+ * Sanity check: if there is a refcount bug, we can't delete
+ * the session a user configured manually. Lets leave a
+ * message here so we can catch the bug if it exists.
+ */
+ if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) {
+ zlog_err(
+ "ptm-del-session: [%s] session refcount is "
+ "zero but it was configured by CLI",
+ bs_to_string(bs));
+ } else {
+ control_notify_config(BCM_NOTIFY_CONFIG_DELETE, bs);
+ bfd_session_free(bs);
+ }
+ }
+}
+
static int _ptm_msg_address(struct stream *msg, int family, const void *addr)
{
stream_putc(msg, family);
@@ -456,15 +485,20 @@ static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id)
/* Unregister client peer notification. */
pcn = pcn_lookup(pc, bs);
- pcn_free(pcn);
- if (bs->refcount ||
- CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG))
+ if (pcn != NULL) {
+ pcn_free(pcn);
return;
+ }
- bs->ses_state = PTM_BFD_ADM_DOWN;
- ptm_bfd_snd(bs, 0);
+ if (bglobal.debug_zebra)
+ zlog_debug("ptm-del-dest: failed to find BFD session");
- ptm_bfd_sess_del(&bpc);
+ /*
+ * XXX: We either got a double deregistration or the daemon who
+ * created this is no longer around. Lets try to delete it anyway
+ * and the worst case is the refcount will detain us.
+ */
+ _ptm_bfd_session_del(bs, BD_NEIGHBOR_DOWN);
}
/*
@@ -506,6 +540,9 @@ static void bfdd_client_deregister(struct stream *msg)
return;
}
+ if (bglobal.debug_zebra)
+ zlog_debug("ptm-del-client: client pid %u", pid);
+
pc_free(pc);
return;
@@ -827,9 +864,6 @@ static void pc_free(struct ptm_client *pc)
{
struct ptm_client_notification *pcn;
- if (pc == NULL)
- return;
-
TAILQ_REMOVE(&pcqueue, pc, pc_entry);
while (!TAILQ_EMPTY(&pc->pc_pcnqueue)) {
@@ -891,14 +925,19 @@ static void pcn_free(struct ptm_client_notification *pcn)
struct ptm_client *pc;
struct bfd_session *bs;
- if (pcn == NULL)
- return;
-
/* Handle session de-registration. */
bs = pcn->pcn_bs;
pcn->pcn_bs = NULL;
bs->refcount--;
+ /* Log modification to users. */
+ if (bglobal.debug_zebra)
+ zlog_debug("ptm-del-session: [%s] refcount=%" PRIu64,
+ bs_to_string(bs), bs->refcount);
+
+ /* Set session down. */
+ _ptm_bfd_session_del(bs, BD_NEIGHBOR_DOWN);
+
/* Handle ptm_client deregistration. */
pc = pcn->pcn_pc;
pcn->pcn_pc = NULL;