diff options
author | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-05-12 21:38:33 +0200 |
---|---|---|
committer | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-05-14 00:41:50 +0200 |
commit | 29191d31832717b7747ee777a500d3b964a35a1a (patch) | |
tree | b0f5edbcd29d5cf07e79c9028f0f2daef994d3c7 /bfdd | |
parent | Merge pull request #6334 from ton31337/fix/labeled_unicast_table_scount (diff) | |
download | frr-29191d31832717b7747ee777a500d3b964a35a1a.tar.xz frr-29191d31832717b7747ee777a500d3b964a35a1a.zip |
bfdd: tell peer when our control plane is dead
Simplify and fix the code that handles session teardown on control
plane shutdown (either failure or graceful).
- Don't move the `NULL` check inside `free` functions that expect
data: it creates harder to understand flows.
- Add some new debug messages to aid visualizing session deletions.
- Add sanity check error message (if it ever happens).
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
Diffstat (limited to 'bfdd')
-rw-r--r-- | bfdd/ptm_adapter.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index 7efbd2c7b..0d5183ed5 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); @@ -453,15 +482,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); } /* @@ -503,6 +537,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; @@ -824,9 +861,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)) { @@ -888,14 +922,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; |