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,