From 0885a9f1f4352996d95766b69fc29e464adee01c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 22 Jun 2017 11:05:03 -0400 Subject: [PATCH] pimd: Fix code to not send joins when SGRPT Prune is received When we receive a SGRPT Prune we were switching the upstream to JOINED and immediately sending a join. This was not the right thing to do. This was happening because we were making decisions about the new ifchannel before it was fully formed. Rework ifchannel startup to provide enough information to the pim upstream data structure to make the right decisions Ticket: CM-16425 Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 2 +- pimd/pim_ifchannel.c | 60 +++++++++++++++++++++++++++----------------- pimd/pim_ifchannel.h | 3 ++- pimd/pim_mroute.c | 4 +-- pimd/pim_msdp.c | 2 +- pimd/pim_register.c | 2 +- pimd/pim_upstream.c | 14 ++++++++--- pimd/pim_upstream.h | 3 ++- 8 files changed, 56 insertions(+), 34 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 6af52bbf4d..934fea5a9e 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -147,7 +147,7 @@ static int dispatch_assert(struct interface *ifp, struct in_addr source_addr, memset(&sg, 0, sizeof(struct prefix_sg)); sg.src = source_addr; sg.grp = group_addr; - ch = pim_ifchannel_add(ifp, &sg, 0); + ch = pim_ifchannel_add(ifp, &sg, 0, 0); if (!ch) { zlog_warn( "%s: (S,G)=%s failure creating channel on interface %s", diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 5f3901e49b..922ee647a5 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -509,7 +509,8 @@ static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch) } struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, - struct prefix_sg *sg, int flags) + struct prefix_sg *sg, + uint8_t source_flags, int up_flags) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; @@ -521,27 +522,19 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_ifp = ifp->info; - up = pim_upstream_add(pim_ifp->pim, sg, NULL, flags, - __PRETTY_FUNCTION__); - if (!up) { - zlog_err( - "%s: could not attach upstream (S,G)=%s on interface %s", - __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); - return NULL; - } - ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); if (!ch) { zlog_warn( "%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", __PRETTY_FUNCTION__, up->sg_str, ifp->name); - - pim_upstream_del(pim_ifp->pim, up, __PRETTY_FUNCTION__); return NULL; } ch->flags = 0; - ch->upstream = up; + if ((source_flags & PIM_ENCODE_RPT_BIT) + && !(source_flags & PIM_ENCODE_WC_BIT)) + PIM_IF_FLAG_SET_S_G_RPT(ch->flags); + ch->interface = ifp; ch->sg = *sg; pim_str_sg_set(sg, ch->sg_str); @@ -561,6 +554,32 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, ch->t_ifjoin_prune_pending_timer = NULL; ch->ifjoin_creation = 0; + /* Attach to list */ + listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); + ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); + listnode_add_sort(pim_ifp->pim->ifchannel_list, ch); + + up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags, + __PRETTY_FUNCTION__, ch); + + if (!up) { + zlog_err( + "%s: could not attach upstream (S,G)=%s on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); + + pim_ifchannel_remove_children(ch); + if (ch) + list_delete(ch->sources); + + listnode_delete(pim_ifp->pim_ifchannel_list, ch); + hash_release(pim_ifp->pim_ifchannel_hash, ch); + listnode_delete(pim_ifp->pim->ifchannel_list, ch); + XFREE(MTYPE_PIM_IFCHANNEL, ch); + return NULL; + } + + listnode_add_sort(up->ifchannels, ch); + ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch); @@ -580,13 +599,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, else PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - /* Attach to list */ - listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); - ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); - listnode_add_sort(pim_ifp->pim->ifchannel_list, ch); - - listnode_add_sort(up->ifchannels, ch); - if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, ch->sg_str); @@ -772,7 +784,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, return; } - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); + ch = pim_ifchannel_add(ifp, sg, source_flags, + PIM_UPSTREAM_FLAG_MASK_SRC_PIM); if (!ch) return; @@ -914,7 +927,8 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, return; } - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); + ch = pim_ifchannel_add(ifp, sg, source_flags, + PIM_UPSTREAM_FLAG_MASK_SRC_PIM); if (!ch) return; @@ -1027,7 +1041,7 @@ int pim_ifchannel_local_membership_add(struct interface *ifp, } } - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); + ch = pim_ifchannel_add(ifp, sg, 0, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); if (!ch) { return 0; } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 2260fd451b..3fd717bec8 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -116,7 +116,8 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp); struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, struct prefix_sg *sg); struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, - struct prefix_sg *sg, int flags); + struct prefix_sg *sg, uint8_t ch_flags, + int up_flags); void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, struct in_addr upstream, struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index fa53e568f4..0e0a275155 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -248,7 +248,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) { up = pim_upstream_add(pim_ifp->pim, &sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, - __PRETTY_FUNCTION__); + __PRETTY_FUNCTION__, NULL); if (!up) { if (PIM_DEBUG_MROUTE) zlog_debug( @@ -520,7 +520,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, if (pim_if_connected_to_source(ifp, sg.src)) { up = pim_upstream_add(pim_ifp->pim, &sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, - __PRETTY_FUNCTION__); + __PRETTY_FUNCTION__, NULL); if (!up) { if (PIM_DEBUG_MROUTE) zlog_debug( diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 3578f005dd..34962122a0 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -205,7 +205,7 @@ static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, * as if a JP message was rxed addressed to the RP itself." */ up = pim_upstream_add(sa->pim, &sa->sg, NULL /* iif */, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP, - __PRETTY_FUNCTION__); + __PRETTY_FUNCTION__, NULL); sa->up = up; if (up) { diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 605dd43d5e..d0de91bb45 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -370,7 +370,7 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, upstream = pim_upstream_add( pim_ifp->pim, &sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, - __PRETTY_FUNCTION__); + __PRETTY_FUNCTION__, NULL); if (!upstream) { zlog_warn("Failure to create upstream state"); return 1; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 7880bfd491..e7987eb6e7 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -602,7 +602,8 @@ int pim_upstream_compare(void *arg1, void *arg2) static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, struct prefix_sg *sg, struct interface *incoming, - int flags) + int flags, + struct pim_ifchannel *ch) { enum pim_rpf_result rpf_result; struct pim_interface *pim_ifp; @@ -617,6 +618,9 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, up->sg = *sg; pim_str_sg_set(sg, up->sg_str); + if (ch) + ch->upstream = up; + up = hash_get(pim->upstream_hash, up, hash_alloc_intern); if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src, sg->grp)) { @@ -748,7 +752,8 @@ struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg, up->ref_count); } } else - up = pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name); + up = pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name, + NULL); return up; } @@ -766,7 +771,8 @@ void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name) struct pim_upstream *pim_upstream_add(struct pim_instance *pim, struct prefix_sg *sg, struct interface *incoming, int flags, - const char *name) + const char *name, + struct pim_ifchannel *ch) { struct pim_upstream *up = NULL; int found = 0; @@ -776,7 +782,7 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim, pim_upstream_ref(up, flags, name); found = 1; } else { - up = pim_upstream_new(pim, sg, incoming, flags); + up = pim_upstream_new(pim, sg, incoming, flags, ch); } if (PIM_DEBUG_TRACE) { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index b261b8cbae..af4af2a369 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -146,7 +146,8 @@ struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg, struct pim_upstream *pim_upstream_add(struct pim_instance *pim, struct prefix_sg *sg, struct interface *ifp, int flags, - const char *name); + const char *name, + struct pim_ifchannel *ch); void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name); struct pim_upstream *pim_upstream_del(struct pim_instance *pim, struct pim_upstream *up, -- 2.39.5