diff options
author | Russ White <russ@riw.us> | 2020-06-16 13:56:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-16 13:56:03 +0200 |
commit | cba183561b53b3562ec7c4dd23115b02efc26e22 (patch) | |
tree | c20fdad7fb77e84d000868b83de74cd7d8f85369 /bfdd | |
parent | Merge pull request #6575 from mjstapp/fix_avoid_clang_add_fetch (diff) | |
parent | bfdd: tell peer when our control plane is dead (diff) | |
download | frr-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.c | 63 |
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; |