]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_upstream.c
Merge pull request #5494 from opensourcerouting/mlag-module
[mirror_frr.git] / pimd / pim_upstream.c
index 2e6c5c7803501e333b7b6ab34bbf63eb8df53733..a0387cdd4a9c58644e2fff5e59773ae40556bf29 100644 (file)
@@ -78,8 +78,13 @@ static void pim_upstream_remove_children(struct pim_instance *pim,
                        child = pim_upstream_del(pim, child,
                                                 __PRETTY_FUNCTION__);
                }
-               if (child)
+               if (child) {
                        child->parent = NULL;
+                       if (PIM_UPSTREAM_FLAG_TEST_USE_RPT(child->flags))
+                               pim_upstream_mroute_iif_update(
+                                               child->channel_oil,
+                                               __func__);
+               }
        }
        list_delete(&up->sources);
 }
@@ -109,6 +114,10 @@ static void pim_upstream_find_new_children(struct pim_instance *pim,
                    && (child != up)) {
                        child->parent = up;
                        listnode_add_sort(up->sources, child);
+                       if (PIM_UPSTREAM_FLAG_TEST_USE_RPT(child->flags))
+                               pim_upstream_mroute_iif_update(
+                                               child->channel_oil,
+                                               __func__);
                }
        }
 }
@@ -141,14 +150,22 @@ static struct pim_upstream *pim_upstream_find_parent(struct pim_instance *pim,
 
 static void upstream_channel_oil_detach(struct pim_upstream *up)
 {
-       if (up->channel_oil) {
+       struct channel_oil *channel_oil = up->channel_oil;
+
+       if (channel_oil) {
                /* Detaching from channel_oil, channel_oil may exist post del,
                   but upstream would not keep reference of it
                 */
-               up->channel_oil->up = NULL;
-               pim_channel_oil_del(up->channel_oil, __PRETTY_FUNCTION__);
+               channel_oil->up = NULL;
                up->channel_oil = NULL;
+
+               /* attempt to delete channel_oil; if channel_oil is being held
+                * because of other references cleanup info such as "Mute"
+                * inferred from the parent upstream
+                */
+               pim_channel_oil_upstream_deref(channel_oil);
        }
+
 }
 
 struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
@@ -159,7 +176,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
        bool notify_msdp = false;
        struct prefix nht_p;
 
-       if (PIM_DEBUG_TRACE)
+       if (PIM_DEBUG_PIM_TRACE)
                zlog_debug(
                        "%s(%s): Delete %s[%s] ref count: %d , flags: %d c_oil ref count %d (Pre decrement)",
                        __PRETTY_FUNCTION__, name, up->sg_str, pim->vrf->name,
@@ -173,6 +190,11 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
        if (up->ref_count >= 1)
                return up;
 
+       if (PIM_DEBUG_TRACE)
+               zlog_debug(
+                               "pim_upstream free vrf:%s %s flags 0x%x",
+                               pim->vrf->name, up->sg_str, up->flags);
+
        THREAD_OFF(up->t_ka_timer);
        THREAD_OFF(up->t_rs_timer);
        THREAD_OFF(up->t_msdp_reg_timer);
@@ -231,7 +253,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
                nht_p.family = AF_INET;
                nht_p.prefixlen = IPV4_MAX_BITLEN;
                nht_p.u.prefix4 = up->upstream_addr;
-               if (PIM_DEBUG_TRACE) {
+               if (PIM_DEBUG_PIM_TRACE) {
                        char buf[PREFIX2STR_BUFFER];
                        prefix2str(&nht_p, buf, sizeof(buf));
                        zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT",
@@ -248,13 +270,13 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
 void pim_upstream_send_join(struct pim_upstream *up)
 {
        if (!up->rpf.source_nexthop.interface) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: up %s RPF is not present",
                                __PRETTY_FUNCTION__, up->sg_str);
                return;
        }
 
-       if (PIM_DEBUG_TRACE) {
+       if (PIM_DEBUG_PIM_TRACE) {
                char rpf_str[PREFIX_STRLEN];
                pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str,
                              sizeof(rpf_str));
@@ -280,7 +302,7 @@ static int on_join_timer(struct thread *t)
        up = THREAD_ARG(t);
 
        if (!up->rpf.source_nexthop.interface) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: up %s RPF is not present",
                        __PRETTY_FUNCTION__, up->sg_str);
                return 0;
@@ -316,7 +338,7 @@ static void join_timer_stop(struct pim_upstream *up)
                                        up->rpf.rpf_addr.u.prefix4);
 
        if (nbr)
-               pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
+               pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
 
        pim_jp_agg_upstream_verification(up, false);
 }
@@ -338,7 +360,7 @@ void join_timer_start(struct pim_upstream *up)
        }
 
        if (nbr)
-               pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1);
+               pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1, nbr);
        else {
                THREAD_OFF(up->t_join_timer);
                thread_add_timer(router->master, on_join_timer, up,
@@ -381,7 +403,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up,
        long join_timer_remain_msec;
 
        if (!up->rpf.source_nexthop.interface) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: up %s RPF is not present",
                                __PRETTY_FUNCTION__, up->sg_str);
                return;
@@ -393,7 +415,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up,
 
        join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer);
 
-       if (PIM_DEBUG_TRACE) {
+       if (PIM_DEBUG_PIM_TRACE) {
                char rpf_str[INET_ADDRSTRLEN];
                pim_inet4_dump("<rpf?>", rpf_addr, rpf_str, sizeof(rpf_str));
                zlog_debug(
@@ -403,7 +425,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up,
        }
 
        if (join_timer_remain_msec < t_joinsuppress_msec) {
-               if (PIM_DEBUG_TRACE) {
+               if (PIM_DEBUG_PIM_TRACE) {
                        zlog_debug(
                                "%s %s: suppressing Join(S,G)=%s for %ld msec",
                                __FILE__, __PRETTY_FUNCTION__, up->sg_str,
@@ -421,7 +443,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
        int t_override_msec;
 
        if (!up->rpf.source_nexthop.interface) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: up %s RPF is not present",
                                __PRETTY_FUNCTION__, up->sg_str);
                return;
@@ -431,7 +453,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
        t_override_msec =
                pim_if_t_override_msec(up->rpf.source_nexthop.interface);
 
-       if (PIM_DEBUG_TRACE) {
+       if (PIM_DEBUG_PIM_TRACE) {
                char rpf_str[INET_ADDRSTRLEN];
                pim_inet4_dump("<rpf?>", up->rpf.rpf_addr.u.prefix4, rpf_str,
                               sizeof(rpf_str));
@@ -442,7 +464,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
        }
 
        if (join_timer_remain_msec > t_override_msec) {
-               if (PIM_DEBUG_TRACE) {
+               if (PIM_DEBUG_PIM_TRACE) {
                        zlog_debug(
                                "%s: decreasing (S,G)=%s join timer to t_override=%d msec",
                                debug_label, up->sg_str, t_override_msec);
@@ -494,7 +516,7 @@ static int pim_upstream_could_register(struct pim_upstream *up)
        if (up->rpf.source_nexthop.interface)
                pim_ifp = up->rpf.source_nexthop.interface->info;
        else {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: up %s RPF is not present",
                                   __PRETTY_FUNCTION__, up->sg_str);
        }
@@ -519,7 +541,8 @@ void pim_upstream_register_reevaluate(struct pim_instance *pim)
                 * is actually active; if it is not kat setup will trigger
                 * source
                 * registration whenever the flow becomes active. */
-               if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || !up->t_ka_timer)
+               if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) ||
+                       !pim_upstream_is_kat_running(up))
                        continue;
 
                if (pim_is_grp_ssm(pim, up->sg.grp)) {
@@ -532,7 +555,8 @@ void pim_upstream_register_reevaluate(struct pim_instance *pim)
                                /* remove regiface from the OIL if it is there*/
                                pim_channel_del_oif(up->channel_oil,
                                                    pim->regiface,
-                                                   PIM_OIF_FLAG_PROTO_PIM);
+                                                   PIM_OIF_FLAG_PROTO_PIM,
+                                                       __func__);
                                up->reg_state = PIM_REG_NOINFO;
                        }
                } else {
@@ -544,13 +568,87 @@ void pim_upstream_register_reevaluate(struct pim_instance *pim)
                                                up->sg_str);
                                pim_channel_add_oif(up->channel_oil,
                                                    pim->regiface,
-                                                   PIM_OIF_FLAG_PROTO_PIM);
+                                                   PIM_OIF_FLAG_PROTO_PIM,
+                                                       __func__);
                                up->reg_state = PIM_REG_JOIN;
                        }
                }
        }
 }
 
+/* RFC7761, Section 4.2 “Data Packet Forwarding Rules” says we should
+ * forward a S -
+ * 1. along the SPT if SPTbit is set
+ * 2. and along the RPT if SPTbit is not set
+ * If forwarding is hw accelerated i.e. control and dataplane components
+ * are separate you may not be able to reliably set SPT bit on intermediate
+ * routers while still fowarding on the (S,G,rpt).
+ *
+ * This macro is a slight deviation on the RFC and uses "traffic-agnostic"
+ * criteria to decide between using the RPT vs. SPT for forwarding.
+ */
+void pim_upstream_update_use_rpt(struct pim_upstream *up,
+                       bool update_mroute)
+{
+       bool old_use_rpt;
+       bool new_use_rpt;
+
+       if (up->sg.src.s_addr == INADDR_ANY)
+               return;
+
+       old_use_rpt = !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags);
+
+       /* We will use the SPT (IIF=RPF_interface(S) if -
+        * 1. We have decided to join the SPT
+        * 2. We are FHR
+        * 3. Source is directly connected
+        * 4. We are RP (parent's IIF is lo or vrf-device)
+        * In all other cases the source will stay along the RPT and
+        * IIF=RPF_interface(RP).
+        */
+       if (up->join_state == PIM_UPSTREAM_JOINED ||
+                       PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) ||
+                       pim_if_connected_to_source(
+                               up->rpf.source_nexthop.interface,
+                               up->sg.src) ||
+                       /* XXX - need to switch this to a more efficient
+                        * lookup API
+                        */
+                       I_am_RP(up->pim, up->sg.grp))
+               /* use SPT */
+               PIM_UPSTREAM_FLAG_UNSET_USE_RPT(up->flags);
+       else
+               /* use RPT */
+               PIM_UPSTREAM_FLAG_SET_USE_RPT(up->flags);
+
+       new_use_rpt = !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags);
+       if (old_use_rpt != new_use_rpt) {
+               if (PIM_DEBUG_PIM_EVENTS)
+                       zlog_debug("%s switched from %s to %s",
+                                       up->sg_str,
+                                       old_use_rpt?"RPT":"SPT",
+                                       new_use_rpt?"RPT":"SPT");
+               if (update_mroute)
+                       pim_upstream_mroute_add(up->channel_oil, __func__);
+       }
+}
+
+/* some events like RP change require re-evaluation of SGrpt across
+ * all groups
+ */
+void pim_upstream_reeval_use_rpt(struct pim_instance *pim)
+{
+       struct pim_upstream *up;
+       struct listnode *node;
+
+       for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) {
+               if (up->sg.src.s_addr == INADDR_ANY)
+                       continue;
+
+               pim_upstream_update_use_rpt(up, true /*update_mroute*/);
+       }
+}
+
 void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
                         enum pim_upstream_state new_state)
 {
@@ -603,21 +701,47 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
                                join_timer_start(up);
                        }
                }
+               if (old_state != new_state)
+                       pim_upstream_update_use_rpt(up, true /*update_mroute*/);
        } else {
+               bool old_use_rpt;
+               bool new_use_rpt;
+               bool send_xg_jp = false;
 
                forward_off(up);
                if (old_state == PIM_UPSTREAM_JOINED)
                        pim_msdp_up_join_state_changed(pim, up);
 
+               if (old_state != new_state) {
+                       old_use_rpt =
+                               !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags);
+                       pim_upstream_update_use_rpt(up, true /*update_mroute*/);
+                       new_use_rpt =
+                               !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags);
+                       if (new_use_rpt &&
+                                       (new_use_rpt != old_use_rpt) &&
+                                       up->parent)
+                               /* we have decided to switch from the SPT back
+                                * to the RPT which means we need to cancel
+                                * any previously sent SGrpt prunes immediately
+                                */
+                               send_xg_jp = true;
+               }
+
                /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards
                   RP.
                   If I am RP for G then send S,G prune to its IIF. */
-               if (pim_upstream_is_sg_rpt(up) && up->parent
-                   && !I_am_RP(pim, up->sg.grp)) {
+               if (pim_upstream_is_sg_rpt(up) && up->parent &&
+                               !I_am_RP(pim, up->sg.grp))
+                       send_xg_jp = true;
+               else
+                       pim_jp_agg_single_upstream_send(&up->rpf, up,
+                                                       0 /* prune */);
+
+               if (send_xg_jp) {
                        if (PIM_DEBUG_PIM_TRACE_DETAIL)
                                zlog_debug(
-                                 "%s: *,G IIF %s S,G IIF %s ",
-                                 __PRETTY_FUNCTION__,
+                                 "re-join RPT; *,G IIF %s S,G IIF %s ",
                                  up->parent->rpf.source_nexthop.interface ?
                                  up->parent->rpf.source_nexthop.interface->name
                                  : "Unknown",
@@ -627,9 +751,7 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
                        pim_jp_agg_single_upstream_send(&up->parent->rpf,
                                                        up->parent,
                                                        1 /* (W,G) Join */);
-               } else
-                       pim_jp_agg_single_upstream_send(&up->rpf, up,
-                                                       0 /* prune */);
+               }
                join_timer_stop(up);
        }
 }
@@ -683,6 +805,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
 
        up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up));
 
+       up->pim = pim;
        up->sg = *sg;
        pim_str_sg_set(sg, up->sg_str);
        if (ch)
@@ -694,7 +817,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
         */
        if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src,
                                      sg->grp)) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: Received a (*,G) with no RP configured",
                                   __PRETTY_FUNCTION__);
        }
@@ -716,7 +839,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
        up->join_state = PIM_UPSTREAM_NOTJOINED;
        up->reg_state = PIM_REG_NOINFO;
        up->state_transition = pim_time_monotonic_sec();
-       up->channel_oil = NULL;
+       up->channel_oil =
+               pim_channel_oil_add(pim, &up->sg, __PRETTY_FUNCTION__);
        up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE;
 
        up->rpf.source_nexthop.interface = NULL;
@@ -736,46 +860,38 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
        if (up->sg.src.s_addr != INADDR_ANY)
                wheel_add_item(pim->upstream_sg_wheel, up);
 
-       if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)) {
+       if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)
+           || PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)) {
                pim_upstream_fill_static_iif(up, incoming);
                pim_ifp = up->rpf.source_nexthop.interface->info;
                assert(pim_ifp);
-               up->channel_oil = pim_channel_oil_add(pim, &up->sg,
-                                                     pim_ifp->mroute_vif_index,
-                                                     __PRETTY_FUNCTION__);
-       } else if (up->upstream_addr.s_addr == INADDR_ANY) {
-               /* Create a dummmy channel oil with incoming ineterface MAXVIFS,
-                * since RP is not configured
-                */
-               up->channel_oil = pim_channel_oil_add(pim, &up->sg, MAXVIFS,
-                                                     __PRETTY_FUNCTION__);
-
-       } else {
-               rpf_result = pim_rpf_update(pim, up, NULL);
+               pim_upstream_update_use_rpt(up,
+                               false /*update_mroute*/);
+               pim_upstream_mroute_iif_update(up->channel_oil, __func__);
+
+               if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags))
+                       pim_upstream_keep_alive_timer_start(
+                               up, pim->keep_alive_time);
+       } else if (up->upstream_addr.s_addr != INADDR_ANY) {
+               pim_upstream_update_use_rpt(up,
+                               false /*update_mroute*/);
+               rpf_result = pim_rpf_update(pim, up, NULL, __func__);
                if (rpf_result == PIM_RPF_FAILURE) {
-                       if (PIM_DEBUG_TRACE)
+                       if (PIM_DEBUG_PIM_TRACE)
                                zlog_debug(
                                        "%s: Attempting to create upstream(%s), Unable to RPF for source",
                                        __PRETTY_FUNCTION__, up->sg_str);
-                       /* Create a dummmy channel oil with incoming ineterface
-                        * MAXVIFS, since RP is not reachable
-                        */
-                       up->channel_oil = pim_channel_oil_add(
-                               pim, &up->sg, MAXVIFS, __PRETTY_FUNCTION__);
                }
 
                if (up->rpf.source_nexthop.interface) {
-                       pim_ifp = up->rpf.source_nexthop.interface->info;
-                       if (pim_ifp)
-                               up->channel_oil = pim_channel_oil_add(
-                                       pim, &up->sg, pim_ifp->mroute_vif_index,
-                                       __PRETTY_FUNCTION__);
+                       pim_upstream_mroute_iif_update(up->channel_oil,
+                                       __func__);
                }
        }
 
        listnode_add_sort(pim->upstream_list, up);
 
-       if (PIM_DEBUG_TRACE) {
+       if (PIM_DEBUG_PIM_TRACE) {
                zlog_debug(
                        "%s: Created Upstream %s upstream_addr %s ref count %d increment",
                        __PRETTY_FUNCTION__, up->sg_str,
@@ -797,38 +913,38 @@ struct pim_upstream *pim_upstream_find(struct pim_instance *pim,
 }
 
 struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
-                                             struct interface *incoming,
-                                             int flags, const char *name)
+               struct interface *incoming,
+               int flags, const char *name)
 {
-       struct pim_upstream *up;
-       struct pim_interface *pim_ifp;
-
-       pim_ifp = incoming->info;
-
-       up = pim_upstream_find(pim_ifp->pim, sg);
-
-       if (up) {
-               if (!(up->flags & flags)) {
-                       up->flags |= flags;
-                       up->ref_count++;
-                       if (PIM_DEBUG_TRACE)
-                               zlog_debug(
-                                       "%s(%s): upstream %s ref count %d increment",
-                                       __PRETTY_FUNCTION__, name, up->sg_str,
-                                       up->ref_count);
-               }
-       } else
-               up = pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name,
-                                     NULL);
+       struct pim_interface *pim_ifp = incoming->info;
 
-       return up;
+       return (pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name,
+                               NULL));
 }
 
 void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name)
 {
+       /* when we go from non-FHR to FHR we need to re-eval traffic
+        * forwarding path
+        */
+       if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) &&
+                       PIM_UPSTREAM_FLAG_TEST_FHR(flags)) {
+               PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
+               pim_upstream_update_use_rpt(up, true /*update_mroute*/);
+       }
+
+       /* re-eval joinDesired; clearing peer-msdp-sa flag can
+        * cause JD to change
+        */
+       if (!PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags) &&
+                       PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags)) {
+               PIM_UPSTREAM_FLAG_SET_SRC_MSDP(up->flags);
+               pim_upstream_update_join_desired(up->pim, up);
+       }
+
        up->flags |= flags;
        ++up->ref_count;
-       if (PIM_DEBUG_TRACE)
+       if (PIM_DEBUG_PIM_TRACE)
                zlog_debug("%s(%s): upstream %s ref count %d increment",
                           __PRETTY_FUNCTION__, name, up->sg_str,
                           up->ref_count);
@@ -851,7 +967,7 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
                up = pim_upstream_new(pim, sg, incoming, flags, ch);
        }
 
-       if (PIM_DEBUG_TRACE) {
+       if (PIM_DEBUG_PIM_TRACE) {
                if (up) {
                        char buf[PREFIX2STR_BUFFER];
                        prefix2str(&up->rpf.rpf_addr, buf, sizeof(buf));
@@ -869,6 +985,36 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
        return up;
 }
 
+/*
+ * Passed in up must be the upstream for ch.  starch is NULL if no
+ * information
+ * This function is copied over from
+ * pim_upstream_evaluate_join_desired_interface but limited to
+ * parent (*,G)'s includes/joins.
+ */
+int pim_upstream_eval_inherit_if(struct pim_upstream *up,
+                                                struct pim_ifchannel *ch,
+                                                struct pim_ifchannel *starch)
+{
+       /* if there is an explicit prune for this interface we cannot
+        * add it to the OIL
+        */
+       if (ch) {
+               if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
+                       return 0;
+       }
+
+       /* Check if the OIF can be inherited fron the (*,G) entry
+        */
+       if (starch) {
+               if (!pim_macro_ch_lost_assert(starch)
+                   && pim_macro_chisin_joins_or_include(starch))
+                       return 1;
+       }
+
+       return 0;
+}
+
 /*
  * Passed in up must be the upstream for ch.  starch is NULL if no
  * information
@@ -890,8 +1036,14 @@ int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
         * joins (*,G)
         */
        if (starch) {
+               /* XXX: check on this with donald
+                * we are looking for PIM_IF_FLAG_MASK_S_G_RPT in
+                * upstream flags?
+                */
+#if 0
                if (PIM_IF_FLAG_TEST_S_G_RPT(starch->upstream->flags))
                        return 0;
+#endif
 
                if (!pim_macro_ch_lost_assert(starch)
                    && pim_macro_chisin_joins_or_include(starch))
@@ -901,56 +1053,77 @@ int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
        return 0;
 }
 
-/*
-  Evaluate JoinDesired(S,G):
-
-  JoinDesired(S,G) is true if there is a downstream (S,G) interface I
-  in the set:
-
-  inherited_olist(S,G) =
-  joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G)
-
-  JoinDesired(S,G) may be affected by changes in the following:
-
-  pim_ifp->primary_address
-  pim_ifp->pim_dr_addr
-  ch->ifassert_winner_metric
-  ch->ifassert_winner
-  ch->local_ifmembership
-  ch->ifjoin_state
-  ch->upstream->rpf.source_nexthop.mrib_metric_preference
-  ch->upstream->rpf.source_nexthop.mrib_route_metric
-  ch->upstream->rpf.source_nexthop.interface
-
-  See also pim_upstream_update_join_desired() below.
+/* Returns true if immediate OIL is empty and is used to evaluate
+ * JoinDesired. See pim_upstream_evaluate_join_desired.
  */
-int pim_upstream_evaluate_join_desired(struct pim_instance *pim,
+static bool pim_upstream_empty_immediate_olist(struct pim_instance *pim,
                                       struct pim_upstream *up)
 {
        struct interface *ifp;
-       struct pim_ifchannel *ch, *starch;
-       struct pim_upstream *starup = up->parent;
-       int ret = 0;
+       struct pim_ifchannel *ch;
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                if (!ifp->info)
                        continue;
 
                ch = pim_ifchannel_find(ifp, &up->sg);
-
-               if (starup)
-                       starch = pim_ifchannel_find(ifp, &starup->sg);
-               else
-                       starch = NULL;
-
-               if (!ch && !starch)
+               if (!ch)
                        continue;
 
-               ret += pim_upstream_evaluate_join_desired_interface(up, ch,
-                                                                   starch);
+               /* If we have even one immediate OIF we can return with
+                * not-empty
+                */
+               if (pim_upstream_evaluate_join_desired_interface(up, ch,
+                                           NULL /* starch */))
+                       return false;
        } /* scan iface channel list */
 
-       return ret; /* false */
+       /* immediate_oil is empty */
+       return true;
+}
+
+
+static inline bool pim_upstream_is_msdp_peer_sa(struct pim_upstream *up)
+{
+       return PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags);
+}
+
+/*
+ *   bool JoinDesired(*,G) {
+ *       if (immediate_olist(*,G) != NULL)
+ *           return TRUE
+ *       else
+ *           return FALSE
+ *   }
+ *
+ *   bool JoinDesired(S,G) {
+ *       return( immediate_olist(S,G) != NULL
+ *           OR ( KeepaliveTimer(S,G) is running
+ *           AND inherited_olist(S,G) != NULL ) )
+ *   }
+ */
+int pim_upstream_evaluate_join_desired(struct pim_instance *pim,
+                                      struct pim_upstream *up)
+{
+       bool empty_imm_oil;
+       bool empty_inh_oil;
+
+       empty_imm_oil = pim_upstream_empty_immediate_olist(pim, up);
+
+       /* (*,G) */
+       if (up->sg.src.s_addr == INADDR_ANY)
+               return !empty_imm_oil;
+
+       /* (S,G) */
+       if (!empty_imm_oil)
+               return true;
+       empty_inh_oil = pim_upstream_empty_inherited_olist(up);
+       if (!empty_inh_oil &&
+                       (pim_upstream_is_kat_running(up) ||
+                        pim_upstream_is_msdp_peer_sa(up)))
+               return true;
+
+       return false;
 }
 
 /*
@@ -1004,7 +1177,7 @@ void pim_upstream_rpf_genid_changed(struct pim_instance *pim,
         */
        for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
 
-               if (PIM_DEBUG_TRACE) {
+               if (PIM_DEBUG_PIM_TRACE) {
                        char neigh_str[INET_ADDRSTRLEN];
                        char rpf_addr_str[PREFIX_STRLEN];
                        pim_inet4_dump("<neigh?>", neigh_addr, neigh_str,
@@ -1113,7 +1286,7 @@ static void pim_upstream_fhr_kat_expiry(struct pim_instance *pim,
        if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags))
                return;
 
-       if (PIM_DEBUG_TRACE)
+       if (PIM_DEBUG_PIM_TRACE)
                zlog_debug("kat expired on %s; clear fhr reg state",
                           up->sg_str);
 
@@ -1121,7 +1294,7 @@ static void pim_upstream_fhr_kat_expiry(struct pim_instance *pim,
        THREAD_OFF(up->t_rs_timer);
        /* remove regiface from the OIL if it is there*/
        pim_channel_del_oif(up->channel_oil, pim->regiface,
-                           PIM_OIF_FLAG_PROTO_PIM);
+                           PIM_OIF_FLAG_PROTO_PIM, __func__);
        /* clear the register state */
        up->reg_state = PIM_REG_NOINFO;
        PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags);
@@ -1133,7 +1306,7 @@ static void pim_upstream_fhr_kat_expiry(struct pim_instance *pim,
 static void pim_upstream_fhr_kat_start(struct pim_upstream *up)
 {
        if (pim_upstream_could_register(up)) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug(
                                "kat started on %s; set fhr reg state to joined",
                                up->sg_str);
@@ -1141,6 +1314,7 @@ static void pim_upstream_fhr_kat_start(struct pim_upstream *up)
                PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
                if (up->reg_state == PIM_REG_NOINFO)
                        pim_register_join(up);
+               pim_upstream_update_use_rpt(up, true /*update_mroute*/);
        }
 }
 
@@ -1176,10 +1350,13 @@ struct pim_upstream *pim_upstream_keep_alive_timer_proc(
        /* source is no longer active - pull the SA from MSDP's cache */
        pim_msdp_sa_local_del(pim, &up->sg);
 
+       /* JoinDesired can change when KAT is started or stopped */
+       pim_upstream_update_join_desired(pim, up);
+
        /* if entry was created because of activity we need to deref it */
        if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
                pim_upstream_fhr_kat_expiry(pim, up);
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug(
                                "kat expired on %s[%s]; remove stream reference",
                                up->sg_str, pim->vrf->name);
@@ -1189,6 +1366,13 @@ struct pim_upstream *pim_upstream_keep_alive_timer_proc(
                if (!pim_upstream_del(pim, up, __PRETTY_FUNCTION__))
                        return NULL;
        }
+       if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)) {
+               PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(up->flags);
+
+               if (!pim_upstream_del(pim, up, __PRETTY_FUNCTION__))
+                       return NULL;
+       }
+
        /* upstream reference would have been added to track the local
         * membership if it is LHR. We have to clear it when KAT expires.
         * Otherwise would result in stale entry with uncleared ref count.
@@ -1220,7 +1404,7 @@ static int pim_upstream_keep_alive_timer(struct thread *t)
 void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time)
 {
        if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("kat start on %s with no stream reference",
                                   up->sg_str);
        }
@@ -1231,6 +1415,8 @@ void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time)
        /* any time keepalive is started against a SG we will have to
         * re-evaluate our active source database */
        pim_msdp_sa_local_update(up);
+       /* JoinDesired can change when KAT is started or stopped */
+       pim_upstream_update_join_desired(up->pim, up);
 }
 
 /* MSDP on RP needs to know if a source is registerable to this RP */
@@ -1280,7 +1466,7 @@ void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)
  *  SwitchToSptDesired(S,G) return true once a single packet has been
  *  received for the source and group.
  */
-int pim_upstream_switch_to_spt_desired(struct pim_instance *pim,
+int pim_upstream_switch_to_spt_desired_on_rp(struct pim_instance *pim,
                                       struct prefix_sg *sg)
 {
        if (I_am_RP(pim, sg->grp))
@@ -1306,14 +1492,14 @@ int pim_upstream_is_sg_rpt(struct pim_upstream *up)
  *   void
  *   Update_SPTbit(S,G,iif) {
  *     if ( iif == RPF_interface(S)
- *           AND JoinDesired(S,G) == TRUE
- *           AND ( DirectlyConnected(S) == TRUE
+ *           AND JoinDesired(S,G) == true
+ *           AND ( DirectlyConnected(S) == true
  *                 OR RPF_interface(S) != RPF_interface(RP(G))
  *                 OR inherited_olist(S,G,rpt) == NULL
  *                 OR ( ( RPF'(S,G) == RPF'(*,G) ) AND
  *                      ( RPF'(S,G) != NULL ) )
  *                 OR ( I_Am_Assert_Loser(S,G,iif) ) {
- *        Set SPTbit(S,G) to TRUE
+ *        Set SPTbit(S,G) to true
  *     }
  *   }
  */
@@ -1324,7 +1510,7 @@ void pim_upstream_set_sptbit(struct pim_upstream *up,
 
        // iif == RPF_interfvace(S)
        if (up->rpf.source_nexthop.interface != incoming) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug(
                                "%s: Incoming Interface: %s is different than RPF_interface(S) %s",
                                __PRETTY_FUNCTION__, incoming->name,
@@ -1332,18 +1518,18 @@ void pim_upstream_set_sptbit(struct pim_upstream *up,
                return;
        }
 
-       // AND JoinDesired(S,G) == TRUE
+       // AND JoinDesired(S,G) == true
        if (!pim_upstream_evaluate_join_desired(up->channel_oil->pim, up)) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: %s Join is not Desired",
                                   __PRETTY_FUNCTION__, up->sg_str);
                return;
        }
 
-       // DirectlyConnected(S) == TRUE
+       // DirectlyConnected(S) == true
        if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
                                       up->sg.src)) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: %s is directly connected to the source",
                                   __PRETTY_FUNCTION__, up->sg_str);
                up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
@@ -1356,7 +1542,7 @@ void pim_upstream_set_sptbit(struct pim_upstream *up,
                               .interface != starup->rpf.source_nexthop.interface) {
                struct pim_upstream *starup = up->parent;
 
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug(
                                "%s: %s RPF_interface(S) != RPF_interface(RP(G))",
                                __PRETTY_FUNCTION__, up->sg_str);
@@ -1369,7 +1555,7 @@ void pim_upstream_set_sptbit(struct pim_upstream *up,
        // OR inherited_olist(S,G,rpt) == NULL
        if (pim_upstream_is_sg_rpt(up)
            && pim_upstream_empty_inherited_olist(up)) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: %s OR inherited_olist(S,G,rpt) == NULL",
                                   __PRETTY_FUNCTION__, up->sg_str);
                up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
@@ -1379,7 +1565,7 @@ void pim_upstream_set_sptbit(struct pim_upstream *up,
        // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND
        //      ( RPF'(S,G) != NULL ) )
        if (up->parent && pim_rpf_is_same(&up->rpf, &up->parent->rpf)) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: %s RPF'(S,G) is the same as RPF'(*,G)",
                                   __PRETTY_FUNCTION__, up->sg_str);
                up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
@@ -1432,7 +1618,7 @@ static int pim_upstream_register_stop_timer(struct thread *t)
        up = THREAD_ARG(t);
        pim = up->channel_oil->pim;
 
-       if (PIM_DEBUG_TRACE) {
+       if (PIM_DEBUG_PIM_TRACE) {
                char state_str[PIM_REG_STATE_STR_LEN];
                zlog_debug("%s: (S,G)=%s[%s] upstream register stop timer %s",
                           __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
@@ -1443,14 +1629,15 @@ static int pim_upstream_register_stop_timer(struct thread *t)
        case PIM_REG_JOIN_PENDING:
                up->reg_state = PIM_REG_JOIN;
                pim_channel_add_oif(up->channel_oil, pim->regiface,
-                                   PIM_OIF_FLAG_PROTO_PIM);
-               pim_vxlan_update_sg_reg_state(pim, up, TRUE /*reg_join*/);
+                                   PIM_OIF_FLAG_PROTO_PIM,
+                                       __func__);
+               pim_vxlan_update_sg_reg_state(pim, up, true /*reg_join*/);
                break;
        case PIM_REG_JOIN:
                break;
        case PIM_REG_PRUNE:
                if (!up->rpf.source_nexthop.interface) {
-                       if (PIM_DEBUG_TRACE)
+                       if (PIM_DEBUG_PIM_TRACE)
                                zlog_debug("%s: up %s RPF is not present",
                                        __PRETTY_FUNCTION__, up->sg_str);
                        return 0;
@@ -1458,7 +1645,7 @@ static int pim_upstream_register_stop_timer(struct thread *t)
 
                pim_ifp = up->rpf.source_nexthop.interface->info;
                if (!pim_ifp) {
-                       if (PIM_DEBUG_TRACE)
+                       if (PIM_DEBUG_PIM_TRACE)
                                zlog_debug(
                                        "%s: Interface: %s is not configured for pim",
                                        __PRETTY_FUNCTION__,
@@ -1471,7 +1658,7 @@ static int pim_upstream_register_stop_timer(struct thread *t)
                if (((up->channel_oil->cc.lastused / 100)
                     > pim->keep_alive_time)
                    && (I_am_RP(pim_ifp->pim, up->sg.grp))) {
-                       if (PIM_DEBUG_TRACE)
+                       if (PIM_DEBUG_PIM_TRACE)
                                zlog_debug(
                                        "%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while",
                                        __PRETTY_FUNCTION__);
@@ -1501,7 +1688,7 @@ void pim_upstream_start_register_stop_timer(struct pim_upstream *up,
        } else
                time = PIM_REGISTER_PROBE_PERIOD;
 
-       if (PIM_DEBUG_TRACE) {
+       if (PIM_DEBUG_PIM_TRACE) {
                zlog_debug(
                        "%s: (S,G)=%s Starting upstream register stop timer %d",
                        __PRETTY_FUNCTION__, up->sg_str, time);
@@ -1514,22 +1701,14 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
                                        struct pim_upstream *up)
 {
        struct interface *ifp;
-       struct pim_interface *pim_ifp = NULL;
        struct pim_ifchannel *ch, *starch;
        struct pim_upstream *starup = up->parent;
        int output_intf = 0;
 
-       if (up->rpf.source_nexthop.interface)
-               pim_ifp = up->rpf.source_nexthop.interface->info;
-       else {
-               if (PIM_DEBUG_TRACE)
+       if (!up->rpf.source_nexthop.interface)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: up %s RPF is not present",
                                   __PRETTY_FUNCTION__, up->sg_str);
-       }
-       if (pim_ifp && !up->channel_oil)
-               up->channel_oil = pim_channel_oil_add(pim, &up->sg,
-                                                     pim_ifp->mroute_vif_index,
-                                                     __PRETTY_FUNCTION__);
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                if (!ifp->info)
@@ -1552,7 +1731,8 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
                        if (!ch)
                                flag = PIM_OIF_FLAG_PROTO_STAR;
 
-                       pim_channel_add_oif(up->channel_oil, ifp, flag);
+                       pim_channel_add_oif(up->channel_oil, ifp, flag,
+                                       __func__);
                        output_intf++;
                }
        }
@@ -1587,9 +1767,9 @@ int pim_upstream_inherited_olist(struct pim_instance *pim,
         * switch on a stick so turn on forwarding to just accept the
         * incoming packets so we don't bother the other stuff!
         */
-       if (output_intf)
-               pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
-       else
+       pim_upstream_update_join_desired(pim, up);
+
+       if (!output_intf)
                forward_on(up);
 
        return output_intf;
@@ -1611,13 +1791,15 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
        struct listnode *up_node;
        struct listnode *up_nextnode;
        struct pim_upstream *up;
+       struct pim_rpf old;
+       enum pim_rpf_result rpf_result;
 
        /*
         * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
         */
        for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
                if (up->upstream_addr.s_addr == INADDR_ANY) {
-                       if (PIM_DEBUG_TRACE)
+                       if (PIM_DEBUG_PIM_TRACE)
                                zlog_debug(
                                    "%s: RP not configured for Upstream %s",
                                    __PRETTY_FUNCTION__, up->sg_str);
@@ -1625,13 +1807,23 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
                }
 
                if (pim_rpf_addr_is_inaddr_any(&up->rpf)) {
-                       if (PIM_DEBUG_TRACE)
+                       if (PIM_DEBUG_PIM_TRACE)
                                zlog_debug(
                                        "%s: Upstream %s without a path to send join, checking",
                                        __PRETTY_FUNCTION__, up->sg_str);
-                       pim_rpf_update(pim, up, NULL);
+                       old.source_nexthop.interface =
+                               up->rpf.source_nexthop.interface;
+                       rpf_result = pim_rpf_update(pim, up, &old, __func__);
+                       if (rpf_result == PIM_RPF_CHANGED ||
+                                       (rpf_result == PIM_RPF_FAILURE &&
+                                        old.source_nexthop.interface))
+                               pim_zebra_upstream_rpf_changed(pim, up, &old);
+                       /* update kernel multicast forwarding cache (MFC) */
+                       pim_upstream_mroute_iif_update(up->channel_oil,
+                                       __func__);
                }
        }
+       pim_zebra_update_all_interfaces(pim);
 }
 
 unsigned int pim_upstream_hash_key(const void *arg)
@@ -1678,7 +1870,7 @@ bool pim_upstream_equal(const void *arg1, const void *arg2)
 /* rfc4601:section-4.2:"Data Packet Forwarding Rules" defines
  * the cases where kat has to be restarted on rxing traffic -
  *
- * if( DirectlyConnected(S) == TRUE AND iif == RPF_interface(S) ) {
+ * if( DirectlyConnected(S) == true AND iif == RPF_interface(S) ) {
  * set KeepaliveTimer(S,G) to Keepalive_Period
  * # Note: a register state transition or UpstreamJPState(S,G)
  * # transition may happen as a result of restarting
@@ -1691,30 +1883,30 @@ bool pim_upstream_equal(const void *arg1, const void *arg2)
  */
 static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
 {
-       struct pim_instance *pim = up->channel_oil->pim;
+       struct channel_oil *c_oil = up->channel_oil;
+       struct interface *ifp = up->rpf.source_nexthop.interface;
+       struct pim_interface *pim_ifp;
+
+       /* "iif == RPF_interface(S)" check is not easy to do as the info
+        * we get from the kernel/ASIC is really a "lookup/key hit".
+        * So we will do an approximate check here to avoid starting KAT
+        * because of (S,G,rpt) forwarding on a non-LHR.
+        */
+       if (!ifp)
+               return false;
 
-       /* "iif == RPF_interface(S)" check has to be done by the kernel or hw
-        * so we will skip that here */
-       if (up->rpf.source_nexthop.interface &&
-               pim_if_connected_to_source(up->rpf.source_nexthop.interface,
+       pim_ifp = ifp->info;
+       if (pim_ifp->mroute_vif_index != c_oil->oil.mfcc_parent)
+               return false;
+
+       if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
                                       up->sg.src)) {
                return true;
        }
 
        if ((up->join_state == PIM_UPSTREAM_JOINED)
-           && !pim_upstream_empty_inherited_olist(up)) {
-               /* XXX: I have added this RP check just for 3.2 and it's a
-                * digression from
-                * what rfc-4601 says. Till now we were only running KAT on FHR
-                * and RP and
-                * there is some angst around making the change to run it all
-                * routers that
-                * maintain the (S, G) state. This is tracked via CM-13601 and
-                * MUST be
-                * removed to handle spt turn-arounds correctly in a 3-tier clos
-                */
-               if (I_am_RP(pim, up->sg.grp))
-                       return true;
+                       && !pim_upstream_empty_inherited_olist(up)) {
+               return true;
        }
 
        return false;
@@ -1731,7 +1923,7 @@ static void pim_upstream_sg_running(void *arg)
 
        // No packet can have arrived here if this is the case
        if (!up->channel_oil->installed) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug("%s: %s%s is not installed in mroute",
                                   __PRETTY_FUNCTION__, up->sg_str,
                                   pim->vrf->name);
@@ -1747,7 +1939,7 @@ static void pim_upstream_sg_running(void *arg)
         * to get us up and working for the moment
         */
        if (up->channel_oil->oil_inherited_rescan) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug(
                                "%s: Handling unscanned inherited_olist for %s[%s]",
                                __PRETTY_FUNCTION__, up->sg_str,
@@ -1760,7 +1952,7 @@ static void pim_upstream_sg_running(void *arg)
        // Have we seen packets?
        if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt)
            && (up->channel_oil->cc.lastused / 100 > 30)) {
-               if (PIM_DEBUG_TRACE) {
+               if (PIM_DEBUG_PIM_TRACE) {
                        zlog_debug(
                                "%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)",
                                __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
@@ -1775,7 +1967,7 @@ static void pim_upstream_sg_running(void *arg)
                /* Add a source reference to the stream if
                 * one doesn't already exist */
                if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
-                       if (PIM_DEBUG_TRACE)
+                       if (PIM_DEBUG_PIM_TRACE)
                                zlog_debug(
                                        "source reference created on kat restart %s[%s]",
                                        up->sg_str, pim->vrf->name);
@@ -1809,7 +2001,7 @@ void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim)
                        continue;
 
                pim_channel_add_oif(up->channel_oil, pim->regiface,
-                                   PIM_OIF_FLAG_PROTO_IGMP);
+                                   PIM_OIF_FLAG_PROTO_IGMP, __func__);
        }
 }
 
@@ -1858,17 +2050,18 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
 
                if (!nlist) {
                        pim_channel_del_oif(up->channel_oil, pim->regiface,
-                                           PIM_OIF_FLAG_PROTO_IGMP);
+                                       PIM_OIF_FLAG_PROTO_IGMP, __func__);
                        continue;
                }
                g.u.prefix4 = up->sg.grp;
                apply_new = prefix_list_apply(np, &g);
                if (apply_new == PREFIX_DENY)
                        pim_channel_add_oif(up->channel_oil, pim->regiface,
-                                           PIM_OIF_FLAG_PROTO_IGMP);
+                                           PIM_OIF_FLAG_PROTO_IGMP,
+                                               __func__);
                else
                        pim_channel_del_oif(up->channel_oil, pim->regiface,
-                                           PIM_OIF_FLAG_PROTO_IGMP);
+                                       PIM_OIF_FLAG_PROTO_IGMP, __func__);
        }
 }