diff options
author | anuradhak <anuradhak@cumulusnetworks.com> | 2016-12-02 06:01:34 +0100 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2016-12-22 02:26:18 +0100 |
commit | 36e466fe98abf3537e641bc31e9f5cfa06c0fc64 (patch) | |
tree | 81b9814c59b4da7c2995bbc30a1554fb95ad6f80 | |
parent | pimd: Fix so creation of prefix happens one time (diff) | |
download | frr-36e466fe98abf3537e641bc31e9f5cfa06c0fc64.tar.xz frr-36e466fe98abf3537e641bc31e9f5cfa06c0fc64.zip |
pimd: Drop local SA reference when the upstream SG is deleted
This is done irrespective of the reason for del and is intended as a
catchall for cases (unclear which ones) where the RP can drop the SG
without KAT expiry.
Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
-rw-r--r-- | pimd/pim_msdp.c | 63 | ||||
-rw-r--r-- | pimd/pim_msdp.h | 5 | ||||
-rw-r--r-- | pimd/pim_upstream.c | 6 |
3 files changed, 68 insertions, 6 deletions
diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index d32798413..c90a7e1e2 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -124,7 +124,9 @@ pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) sa->up = NULL; if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); + sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG; pim_upstream_del(up, __PRETTY_FUNCTION__); + sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG; } if (PIM_DEBUG_MSDP_EVENTS) { @@ -234,7 +236,7 @@ pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp) sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); if (!sa) { zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*sa)); + __PRETTY_FUNCTION__, sizeof(*sa)); return NULL; } @@ -477,6 +479,50 @@ pim_msdp_sa_local_del(struct prefix_sg *sg) } } +/* we need to be very cautious with this API as SA del too can trigger an + * upstream del and we will get stuck in a simple loop */ +static void +pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) +{ + struct pim_msdp_sa *sa; + + sa = pim_msdp_sa_find(sg); + if (sa) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del on up del", sa->sg_str); + } + + /* if there is no local reference escape */ + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del; no local ref", sa->sg_str); + } + return; + } + + if (sa->flags & PIM_MSDP_SAF_UP_DEL_IN_PROG) { + /* MSDP is the one that triggered the upstream del. if this happens + * we most certainly have a bug in the PIM upstream state machine. We + * will not have a local reference unless the KAT is running. And if the + * KAT is running there MUST be an additional source-stream reference to + * the flow. Accounting for such cases requires lot of changes; perhaps + * address this in the next release? - XXX */ + zlog_err("MSDP sa %s SPT teardown is causing the local entry to be removed", sa->sg_str); + return; + } + + /* we are dropping the sa on upstream del we should not have an + * upstream reference */ + if (sa->up) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del; up non-NULL", sa->sg_str); + } + sa->up = NULL; + } + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } +} + /* Local SA qualification needs to be re-evaluated when - * 1. KAT is started or stopped * 2. on RP changes @@ -579,7 +625,7 @@ pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) } } -void +static void pim_msdp_up_xg_del(struct prefix_sg *sg) { struct listnode *sanode; @@ -605,6 +651,19 @@ pim_msdp_up_xg_del(struct prefix_sg *sg) } } +void +pim_msdp_up_del(struct prefix_sg *sg) +{ + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); + } + if (sg->src.s_addr == INADDR_ANY) { + pim_msdp_up_xg_del(sg); + } else { + pim_msdp_sa_local_del_on_up_del(sg); + } +} + /* sa hash and peer list helpers */ static unsigned int pim_msdp_sa_hash_key_make(void *p) diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 80d928a05..33c1d88a4 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -69,8 +69,9 @@ enum pim_msdp_sa_flags { * checks) */ PIM_MSDP_SAF_PEER = (1 << 1), PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), - PIM_MSDP_SAF_STALE = (1 << 2) /* local entries can get kicked out on + PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on * misc pim events such as RP change */ + PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3) }; struct pim_msdp_sa { @@ -223,7 +224,7 @@ void pim_msdp_sa_local_del(struct prefix_sg *sg); void pim_msdp_i_am_rp_changed(void); bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp); void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up); -void pim_msdp_up_xg_del(struct prefix_sg *sg); +void pim_msdp_up_del(struct prefix_sg *sg); enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip); enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip); enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index ec985076d..d823934e8 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -187,8 +187,10 @@ pim_upstream_del(struct pim_upstream *up, const char *name) } } - if (up->sg.src.s_addr != INADDR_ANY) + if (up->sg.src.s_addr != INADDR_ANY) { wheel_remove_item (pim_upstream_sg_wheel, up); + notify_msdp = true; + } pim_upstream_remove_children (up); pim_mroute_del (up->channel_oil); @@ -212,7 +214,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) hash_release (pim_upstream_hash, up); if (notify_msdp) { - pim_msdp_up_xg_del(&up->sg); + pim_msdp_up_del(&up->sg); } pim_upstream_free(up); } |