]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_zebra.c
*: reindent
[mirror_frr.git] / pimd / pim_zebra.c
index b4fff971202c3533c82750ef976390d45b25a2a4..c5cca7d1b48b743d8e08958ec3032a2cc9148063 100644 (file)
@@ -58,906 +58,950 @@ static struct zclient *zclient = NULL;
 static int pim_router_id_update_zebra(int command, struct zclient *zclient,
                                      zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct prefix router_id;
+       struct prefix router_id;
 
-  zebra_router_id_update_read(zclient->ibuf, &router_id);
+       zebra_router_id_update_read(zclient->ibuf, &router_id);
 
-  return 0;
+       return 0;
 }
 
 static int pim_zebra_if_add(int command, struct zclient *zclient,
                            zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct interface *ifp;
-
-  /*
-    zebra api adds/dels interfaces using the same call
-    interface_add_read below, see comments in lib/zclient.c
-  */
-  ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
-  if (!ifp)
-    return 0;
-
-  if (PIM_DEBUG_ZEBRA) {
-    zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
-              __PRETTY_FUNCTION__,
-              ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
-              ifp->mtu, if_is_operative(ifp));
-  }
-
-  if (if_is_operative(ifp))
-    pim_if_addr_add_all(ifp);
-
-  return 0;
+       struct interface *ifp;
+
+       /*
+         zebra api adds/dels interfaces using the same call
+         interface_add_read below, see comments in lib/zclient.c
+       */
+       ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
+       if (!ifp)
+               return 0;
+
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug(
+                       "%s: %s index %d flags %ld metric %d mtu %d operative %d",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+                       (long)ifp->flags, ifp->metric, ifp->mtu,
+                       if_is_operative(ifp));
+       }
+
+       if (if_is_operative(ifp))
+               pim_if_addr_add_all(ifp);
+
+       return 0;
 }
 
 static int pim_zebra_if_del(int command, struct zclient *zclient,
                            zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct interface *ifp;
-
-  /*
-    zebra api adds/dels interfaces using the same call
-    interface_add_read below, see comments in lib/zclient.c
-    
-    comments in lib/zclient.c seem to indicate that calling
-    zebra_interface_add_read is the correct call, but that
-    results in an attemted out of bounds read which causes
-    pimd to assert. Other clients use zebra_interface_state_read
-    and it appears to work just fine.
-  */
-  ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
-  if (!ifp)
-    return 0;
-
-  if (PIM_DEBUG_ZEBRA) {
-    zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
-              __PRETTY_FUNCTION__,
-              ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
-              ifp->mtu, if_is_operative(ifp));
-  }
-
-  if (!if_is_operative(ifp))
-    pim_if_addr_del_all(ifp);
-
-  return 0;
+       struct interface *ifp;
+
+       /*
+         zebra api adds/dels interfaces using the same call
+         interface_add_read below, see comments in lib/zclient.c
+
+         comments in lib/zclient.c seem to indicate that calling
+         zebra_interface_add_read is the correct call, but that
+         results in an attemted out of bounds read which causes
+         pimd to assert. Other clients use zebra_interface_state_read
+         and it appears to work just fine.
+       */
+       ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
+       if (!ifp)
+               return 0;
+
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug(
+                       "%s: %s index %d flags %ld metric %d mtu %d operative %d",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+                       (long)ifp->flags, ifp->metric, ifp->mtu,
+                       if_is_operative(ifp));
+       }
+
+       if (!if_is_operative(ifp))
+               pim_if_addr_del_all(ifp);
+
+       return 0;
 }
 
 static int pim_zebra_if_state_up(int command, struct zclient *zclient,
                                 zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct interface *ifp;
-
-  /*
-    zebra api notifies interface up/down events by using the same call
-    zebra_interface_state_read below, see comments in lib/zclient.c
-  */
-  ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
-  if (!ifp)
-    return 0;
-
-  if (PIM_DEBUG_ZEBRA) {
-    zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
-              __PRETTY_FUNCTION__,
-              ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
-              ifp->mtu, if_is_operative(ifp));
-  }
-
-  if (if_is_operative(ifp)) {
-    /*
-      pim_if_addr_add_all() suffices for bringing up both IGMP and PIM
-    */
-    pim_if_addr_add_all(ifp);
-  }
-
-  return 0;
+       struct interface *ifp;
+
+       /*
+         zebra api notifies interface up/down events by using the same call
+         zebra_interface_state_read below, see comments in lib/zclient.c
+       */
+       ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
+       if (!ifp)
+               return 0;
+
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug(
+                       "%s: %s index %d flags %ld metric %d mtu %d operative %d",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+                       (long)ifp->flags, ifp->metric, ifp->mtu,
+                       if_is_operative(ifp));
+       }
+
+       if (if_is_operative(ifp)) {
+               /*
+                 pim_if_addr_add_all() suffices for bringing up both IGMP and
+                 PIM
+               */
+               pim_if_addr_add_all(ifp);
+       }
+
+       return 0;
 }
 
 static int pim_zebra_if_state_down(int command, struct zclient *zclient,
                                   zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct interface *ifp;
-
-  /*
-    zebra api notifies interface up/down events by using the same call
-    zebra_interface_state_read below, see comments in lib/zclient.c
-  */
-  ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
-  if (!ifp)
-    return 0;
-
-  if (PIM_DEBUG_ZEBRA) {
-    zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
-              __PRETTY_FUNCTION__,
-              ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
-              ifp->mtu, if_is_operative(ifp));
-  }
-
-  if (!if_is_operative(ifp)) {
-    pim_ifchannel_delete_all(ifp);
-    /*
-      pim_if_addr_del_all() suffices for shutting down IGMP,
-      but not for shutting down PIM
-    */
-    pim_if_addr_del_all(ifp);
-
-    /*
-      pim_sock_delete() closes the socket, stops read and timer threads,
-      and kills all neighbors.
-    */
-    if (ifp->info) {
-      pim_sock_delete(ifp, "link down");
-    }
-  }
-
-  if (ifp->info)
-    pim_if_del_vif(ifp);
-
-  return 0;
+       struct interface *ifp;
+
+       /*
+         zebra api notifies interface up/down events by using the same call
+         zebra_interface_state_read below, see comments in lib/zclient.c
+       */
+       ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
+       if (!ifp)
+               return 0;
+
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug(
+                       "%s: %s index %d flags %ld metric %d mtu %d operative %d",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+                       (long)ifp->flags, ifp->metric, ifp->mtu,
+                       if_is_operative(ifp));
+       }
+
+       if (!if_is_operative(ifp)) {
+               pim_ifchannel_delete_all(ifp);
+               /*
+                 pim_if_addr_del_all() suffices for shutting down IGMP,
+                 but not for shutting down PIM
+               */
+               pim_if_addr_del_all(ifp);
+
+               /*
+                 pim_sock_delete() closes the socket, stops read and timer
+                 threads,
+                 and kills all neighbors.
+               */
+               if (ifp->info) {
+                       pim_sock_delete(ifp, "link down");
+               }
+       }
+
+       if (ifp->info)
+               pim_if_del_vif(ifp);
+
+       return 0;
 }
 
 #ifdef PIM_DEBUG_IFADDR_DUMP
 static void dump_if_address(struct interface *ifp)
 {
-  struct connected *ifc;
-  struct listnode *node;
-
-  zlog_debug("%s %s: interface %s addresses:",
-            __FILE__, __PRETTY_FUNCTION__,
-            ifp->name);
-  
-  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
-    struct prefix *p = ifc->address;
-    
-    if (p->family != AF_INET)
-      continue;
-    
-    zlog_debug("%s %s: interface %s address %s %s",
-              __FILE__, __PRETTY_FUNCTION__,
-              ifp->name,
-              inet_ntoa(p->u.prefix4),
-              CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? 
-              "secondary" : "primary");
-  }
+       struct connected *ifc;
+       struct listnode *node;
+
+       zlog_debug("%s %s: interface %s addresses:", __FILE__,
+                  __PRETTY_FUNCTION__, ifp->name);
+
+       for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
+               struct prefix *p = ifc->address;
+
+               if (p->family != AF_INET)
+                       continue;
+
+               zlog_debug("%s %s: interface %s address %s %s", __FILE__,
+                          __PRETTY_FUNCTION__, ifp->name,
+                          inet_ntoa(p->u.prefix4),
+                          CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
+                                  ? "secondary"
+                                  : "primary");
+       }
 }
 #endif
 
 static int pim_zebra_if_address_add(int command, struct zclient *zclient,
                                    zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct connected *c;
-  struct prefix *p;
-  struct pim_interface *pim_ifp;
-
-  /*
-    zebra api notifies address adds/dels events by using the same call
-    interface_add_read below, see comments in lib/zclient.c
-
-    zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
-    will add address to interface list by calling
-    connected_add_by_prefix()
-  */
-  c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
-  if (!c)
-    return 0;
-
-  pim_ifp = c->ifp->info;
-  p = c->address;
-
-  if (PIM_DEBUG_ZEBRA) {
-    char buf[BUFSIZ];
-    prefix2str(p, buf, BUFSIZ);
-    zlog_debug("%s: %s connected IP address %s flags %u %s",
-              __PRETTY_FUNCTION__,
-              c->ifp->name, buf, c->flags,
-              CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
-    
+       struct connected *c;
+       struct prefix *p;
+       struct pim_interface *pim_ifp;
+
+       /*
+         zebra api notifies address adds/dels events by using the same call
+         interface_add_read below, see comments in lib/zclient.c
+
+         zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
+         will add address to interface list by calling
+         connected_add_by_prefix()
+       */
+       c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
+       if (!c)
+               return 0;
+
+       pim_ifp = c->ifp->info;
+       p = c->address;
+
+       if (PIM_DEBUG_ZEBRA) {
+               char buf[BUFSIZ];
+               prefix2str(p, buf, BUFSIZ);
+               zlog_debug("%s: %s connected IP address %s flags %u %s",
+                          __PRETTY_FUNCTION__, c->ifp->name, buf, c->flags,
+                          CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
+                                  ? "secondary"
+                                  : "primary");
+
 #ifdef PIM_DEBUG_IFADDR_DUMP
-    dump_if_address(c->ifp);
+               dump_if_address(c->ifp);
 #endif
-  }
+       }
 
-  if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
-    /* trying to add primary address */
+       if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
+               /* trying to add primary address */
 
-    struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
-    if (p->family != AF_INET || primary_addr.s_addr != p->u.prefix4.s_addr) {
-      if (PIM_DEBUG_ZEBRA) {
-       /* but we had a primary address already */
+               struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
+               if (p->family != AF_INET
+                   || primary_addr.s_addr != p->u.prefix4.s_addr) {
+                       if (PIM_DEBUG_ZEBRA) {
+                               /* but we had a primary address already */
 
-       char buf[BUFSIZ];
+                               char buf[BUFSIZ];
 
-       prefix2str(p, buf, BUFSIZ);
+                               prefix2str(p, buf, BUFSIZ);
 
-       zlog_warn("%s: %s : forcing secondary flag on %s",
-                 __PRETTY_FUNCTION__,
-                 c->ifp->name, buf);
-      }
-      SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
-    }
-  }
+                               zlog_warn(
+                                       "%s: %s : forcing secondary flag on %s",
+                                       __PRETTY_FUNCTION__, c->ifp->name, buf);
+                       }
+                       SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
+               }
+       }
 
-  pim_if_addr_add(c);
-  if (pim_ifp)
-    pim_rp_check_on_if_add(pim_ifp);
+       pim_if_addr_add(c);
+       if (pim_ifp)
+               pim_rp_check_on_if_add(pim_ifp);
 
-  if (if_is_loopback (c->ifp))
-    {
-      struct listnode *ifnode;
-      struct interface *ifp;
+       if (if_is_loopback(c->ifp)) {
+               struct listnode *ifnode;
+               struct interface *ifp;
 
-      for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp))
-        {
-         if (!if_is_loopback (ifp) && if_is_operative (ifp))
-           pim_if_addr_add_all (ifp);
-        }
-    }
+               for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode,
+                                         ifp)) {
+                       if (!if_is_loopback(ifp) && if_is_operative(ifp))
+                               pim_if_addr_add_all(ifp);
+               }
+       }
 
-  return 0;
+       return 0;
 }
 
 static int pim_zebra_if_address_del(int command, struct zclient *client,
                                    zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct connected *c;
-  struct prefix *p;
-
-  /*
-    zebra api notifies address adds/dels events by using the same call
-    interface_add_read below, see comments in lib/zclient.c
-
-    zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
-    will remove address from interface list by calling
-    connected_delete_by_prefix()
-  */
-  c = zebra_interface_address_read(command, client->ibuf, vrf_id);
-  if (!c)
-    return 0;
-  
-  p = c->address;
-  if (p->family == AF_INET)
-    {
-        if (PIM_DEBUG_ZEBRA) {
-          char buf[BUFSIZ];
-          prefix2str(p, buf, BUFSIZ);
-          zlog_debug("%s: %s disconnected IP address %s flags %u %s",
-                     __PRETTY_FUNCTION__,
-                     c->ifp->name, buf, c->flags,
-                     CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
+       struct connected *c;
+       struct prefix *p;
+
+       /*
+         zebra api notifies address adds/dels events by using the same call
+         interface_add_read below, see comments in lib/zclient.c
+
+         zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
+         will remove address from interface list by calling
+         connected_delete_by_prefix()
+       */
+       c = zebra_interface_address_read(command, client->ibuf, vrf_id);
+       if (!c)
+               return 0;
+
+       p = c->address;
+       if (p->family == AF_INET) {
+               if (PIM_DEBUG_ZEBRA) {
+                       char buf[BUFSIZ];
+                       prefix2str(p, buf, BUFSIZ);
+                       zlog_debug(
+                               "%s: %s disconnected IP address %s flags %u %s",
+                               __PRETTY_FUNCTION__, c->ifp->name, buf,
+                               c->flags,
+                               CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
+                                       ? "secondary"
+                                       : "primary");
 
 #ifdef PIM_DEBUG_IFADDR_DUMP
-          dump_if_address(c->ifp);
+                       dump_if_address(c->ifp);
 #endif
-        }
+               }
 
-        pim_if_addr_del(c, 0);
-        pim_rp_setup();
-        pim_i_am_rp_re_evaluate();
-    }
+               pim_if_addr_del(c, 0);
+               pim_rp_setup();
+               pim_i_am_rp_re_evaluate();
+       }
 
-  connected_free (c);
-  return 0;
+       connected_free(c);
+       return 0;
 }
 
 static void scan_upstream_rpf_cache()
 {
-  struct listnode     *up_node;
-  struct listnode     *ifnode;
-  struct listnode     *up_nextnode;
-  struct listnode     *node;
-  struct pim_upstream *up;
-  struct interface    *ifp;
-
-  for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) {
-    enum pim_rpf_result rpf_result;
-    struct pim_rpf      old;
-    struct prefix nht_p;
-
-    nht_p.family = AF_INET;
-    nht_p.prefixlen = IPV4_MAX_BITLEN;
-    nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
-    pim_resolve_upstream_nh (&nht_p);
-
-    old.source_nexthop.interface = up->rpf.source_nexthop.interface;
-    old.source_nexthop.nbr       = up->rpf.source_nexthop.nbr;
-    rpf_result = pim_rpf_update(up, &old, 0);
-
-    if (rpf_result == PIM_RPF_FAILURE)
-      continue;
-
-    if (rpf_result == PIM_RPF_CHANGED) {
-      struct pim_neighbor *nbr;
-
-      nbr = pim_neighbor_find (old.source_nexthop.interface,
-                               old.rpf_addr.u.prefix4);
-      if (nbr)
-        pim_jp_agg_remove_group (nbr->upstream_jp_agg, up);
-
-      /*
-       * We have detected a case where we might need to rescan
-       * the inherited o_list so do it.
-       */
-      if (up->channel_oil->oil_inherited_rescan)
-       {
-         pim_upstream_inherited_olist_decide (up);
-         up->channel_oil->oil_inherited_rescan = 0;
-       }
-
-      if (up->join_state == PIM_UPSTREAM_JOINED) {
-       /*
-         * If we come up real fast we can be here
-        * where the mroute has not been installed
-        * so install it.
-        */
-       if (!up->channel_oil->installed)
-         pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__);
-
-        /*
-         * RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Messages
-         *
-         * Transitions from Joined State
-         *
-         * RPF'(S,G) changes not due to an Assert
-         *
-         * The upstream (S,G) state machine remains in Joined
-         * state. Send Join(S,G) to the new upstream neighbor, which is
-         * the new value of RPF'(S,G).  Send Prune(S,G) to the old
-         * upstream neighbor, which is the old value of RPF'(S,G).  Set
-         * the Join Timer (JT) to expire after t_periodic seconds.
-         */
-        pim_jp_agg_switch_interface (&old, &up->rpf, up);
-
-        pim_upstream_join_timer_restart(up, &old);
-      } /* up->join_state == PIM_UPSTREAM_JOINED */
-
-      /* FIXME can join_desired actually be changed by pim_rpf_update()
-        returning PIM_RPF_CHANGED ? */
-      pim_upstream_update_join_desired(up);
-
-    } /* PIM_RPF_CHANGED */
-
-  } /* for (qpim_upstream_list) */
-
-  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp))
-    if (ifp->info)
-      {
-        struct pim_interface *pim_ifp = ifp->info;
-        struct pim_iface_upstream_switch *us;
-
-        for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node, us))
-          {
-            struct pim_rpf rpf;
-            rpf.source_nexthop.interface = ifp;
-            rpf.rpf_addr.u.prefix4 = us->address;
-            pim_joinprune_send(&rpf, us->us);
-            pim_jp_agg_clear_group(us->us);
-          }
-      }
+       struct listnode *up_node;
+       struct listnode *ifnode;
+       struct listnode *up_nextnode;
+       struct listnode *node;
+       struct pim_upstream *up;
+       struct interface *ifp;
+
+       for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) {
+               enum pim_rpf_result rpf_result;
+               struct pim_rpf old;
+               struct prefix nht_p;
+
+               nht_p.family = AF_INET;
+               nht_p.prefixlen = IPV4_MAX_BITLEN;
+               nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+               pim_resolve_upstream_nh(&nht_p);
+
+               old.source_nexthop.interface = up->rpf.source_nexthop.interface;
+               old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
+               rpf_result = pim_rpf_update(up, &old, 0);
+
+               if (rpf_result == PIM_RPF_FAILURE)
+                       continue;
+
+               if (rpf_result == PIM_RPF_CHANGED) {
+                       struct pim_neighbor *nbr;
+
+                       nbr = pim_neighbor_find(old.source_nexthop.interface,
+                                               old.rpf_addr.u.prefix4);
+                       if (nbr)
+                               pim_jp_agg_remove_group(nbr->upstream_jp_agg,
+                                                       up);
+
+                       /*
+                        * We have detected a case where we might need to rescan
+                        * the inherited o_list so do it.
+                        */
+                       if (up->channel_oil->oil_inherited_rescan) {
+                               pim_upstream_inherited_olist_decide(up);
+                               up->channel_oil->oil_inherited_rescan = 0;
+                       }
+
+                       if (up->join_state == PIM_UPSTREAM_JOINED) {
+                               /*
+                                * If we come up real fast we can be here
+                                * where the mroute has not been installed
+                                * so install it.
+                                */
+                               if (!up->channel_oil->installed)
+                                       pim_mroute_add(up->channel_oil,
+                                                      __PRETTY_FUNCTION__);
+
+                               /*
+                                * RFC 4601: 4.5.7.  Sending (S,G) Join/Prune
+                                * Messages
+                                *
+                                * Transitions from Joined State
+                                *
+                                * RPF'(S,G) changes not due to an Assert
+                                *
+                                * The upstream (S,G) state machine remains in
+                                * Joined
+                                * state. Send Join(S,G) to the new upstream
+                                * neighbor, which is
+                                * the new value of RPF'(S,G).  Send Prune(S,G)
+                                * to the old
+                                * upstream neighbor, which is the old value of
+                                * RPF'(S,G).  Set
+                                * the Join Timer (JT) to expire after
+                                * t_periodic seconds.
+                                */
+                               pim_jp_agg_switch_interface(&old, &up->rpf, up);
+
+                               pim_upstream_join_timer_restart(up, &old);
+                       } /* up->join_state == PIM_UPSTREAM_JOINED */
+
+                       /* FIXME can join_desired actually be changed by
+                          pim_rpf_update()
+                          returning PIM_RPF_CHANGED ? */
+                       pim_upstream_update_join_desired(up);
+
+               } /* PIM_RPF_CHANGED */
+
+       } /* for (qpim_upstream_list) */
+
+       for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp))
+               if (ifp->info) {
+                       struct pim_interface *pim_ifp = ifp->info;
+                       struct pim_iface_upstream_switch *us;
+
+                       for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list,
+                                                 node, us)) {
+                               struct pim_rpf rpf;
+                               rpf.source_nexthop.interface = ifp;
+                               rpf.rpf_addr.u.prefix4 = us->address;
+                               pim_joinprune_send(&rpf, us->us);
+                               pim_jp_agg_clear_group(us->us);
+                       }
+               }
 }
 
-void
-pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index)
+void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
 {
-  struct in_addr vif_source;
-  int input_iface_vif_index;
-  int old_vif_index;
-
-  if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin, c_oil->oil.mfcc_mcastgrp))
-    return;
-
-  if (in_vif_index)
-    input_iface_vif_index = in_vif_index;
-  else
-    {
-      struct prefix src, grp;
-
-      src.family = AF_INET;
-      src.prefixlen = IPV4_MAX_BITLEN;
-      src.u.prefix4 = vif_source;
-      grp.family = AF_INET;
-      grp.prefixlen = IPV4_MAX_BITLEN;
-      grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
-
-      if (PIM_DEBUG_ZEBRA)
-        {
-          char source_str[INET_ADDRSTRLEN];
-          char group_str[INET_ADDRSTRLEN];
-          pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
-          pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
-          zlog_debug ("%s: channel_oil (%s, %s) upstream info is not present.",
-                      __PRETTY_FUNCTION__, source_str, group_str);
-        }
-      input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp);
-    }
-
-  if (input_iface_vif_index < 1)
-    {
-      if (PIM_DEBUG_ZEBRA)
-        {
-          char source_str[INET_ADDRSTRLEN];
-          char group_str[INET_ADDRSTRLEN];
-          pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
-          pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
-          zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
-                    __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent,
-                    source_str, group_str);
-        }
-      pim_mroute_del (c_oil, __PRETTY_FUNCTION__);
-      return;
-    }
-
-  if (input_iface_vif_index == c_oil->oil.mfcc_parent)
-    {
-      if (!c_oil->installed)
-        pim_mroute_add (c_oil, __PRETTY_FUNCTION__);
-
-      /* RPF unchanged */
-      return;
-    }
-
-  if (PIM_DEBUG_ZEBRA)
-    {
-      struct interface *old_iif = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
-      struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
-      char source_str[INET_ADDRSTRLEN];
-      char group_str[INET_ADDRSTRLEN];
-      pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
-      pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
-      zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
-                __FILE__, __PRETTY_FUNCTION__,
-                source_str, group_str,
-                old_iif->name, c_oil->oil.mfcc_parent,
-                new_iif->name, input_iface_vif_index);
-    }
-
-  /* new iif loops to existing oif ? */
-  if (c_oil->oil.mfcc_ttls[input_iface_vif_index])
-    {
-      struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
-
-      if (PIM_DEBUG_ZEBRA) {
-       char source_str[INET_ADDRSTRLEN];
-       char group_str[INET_ADDRSTRLEN];
-       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
-       pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
-       zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
-                  __FILE__, __PRETTY_FUNCTION__,
-                  source_str, group_str,
-                  new_iif->name, input_iface_vif_index);
-      }
-    }
-
-    /* update iif vif_index */
-    old_vif_index = c_oil->oil.mfcc_parent;
-    c_oil->oil.mfcc_parent = input_iface_vif_index;
-
-    /* update kernel multicast forwarding cache (MFC) */
-    if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__))
-      {
-       if (PIM_DEBUG_MROUTE)
-         {
-           /* just log warning */
-           struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index);
-           struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
-           char source_str[INET_ADDRSTRLEN];
-           char group_str[INET_ADDRSTRLEN];
-           pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
-           pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
-           zlog_debug("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
-                      __FILE__, __PRETTY_FUNCTION__,
-                      source_str, group_str,
-                      old_iif ? old_iif->name : "<old_iif?>", c_oil->oil.mfcc_parent,
-                      new_iif ? new_iif->name : "<new_iif?>", input_iface_vif_index);
-         }
-    }
+       struct in_addr vif_source;
+       int input_iface_vif_index;
+       int old_vif_index;
+
+       if (!pim_rp_set_upstream_addr(&vif_source, c_oil->oil.mfcc_origin,
+                                     c_oil->oil.mfcc_mcastgrp))
+               return;
+
+       if (in_vif_index)
+               input_iface_vif_index = in_vif_index;
+       else {
+               struct prefix src, grp;
+
+               src.family = AF_INET;
+               src.prefixlen = IPV4_MAX_BITLEN;
+               src.u.prefix4 = vif_source;
+               grp.family = AF_INET;
+               grp.prefixlen = IPV4_MAX_BITLEN;
+               grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
+
+               if (PIM_DEBUG_ZEBRA) {
+                       char source_str[INET_ADDRSTRLEN];
+                       char group_str[INET_ADDRSTRLEN];
+                       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
+                                      source_str, sizeof(source_str));
+                       pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
+                                      group_str, sizeof(group_str));
+                       zlog_debug(
+                               "%s: channel_oil (%s, %s) upstream info is not present.",
+                               __PRETTY_FUNCTION__, source_str, group_str);
+               }
+               input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
+                       vif_source, &src, &grp);
+       }
+
+       if (input_iface_vif_index < 1) {
+               if (PIM_DEBUG_ZEBRA) {
+                       char source_str[INET_ADDRSTRLEN];
+                       char group_str[INET_ADDRSTRLEN];
+                       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
+                                      source_str, sizeof(source_str));
+                       pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
+                                      group_str, sizeof(group_str));
+                       zlog_debug(
+                               "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
+                               __FILE__, __PRETTY_FUNCTION__,
+                               c_oil->oil.mfcc_parent, source_str, group_str);
+               }
+               pim_mroute_del(c_oil, __PRETTY_FUNCTION__);
+               return;
+       }
+
+       if (input_iface_vif_index == c_oil->oil.mfcc_parent) {
+               if (!c_oil->installed)
+                       pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
+
+               /* RPF unchanged */
+               return;
+       }
+
+       if (PIM_DEBUG_ZEBRA) {
+               struct interface *old_iif =
+                       pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
+               struct interface *new_iif =
+                       pim_if_find_by_vif_index(input_iface_vif_index);
+               char source_str[INET_ADDRSTRLEN];
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
+                              sizeof(source_str));
+               pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
+                              sizeof(group_str));
+               zlog_debug(
+                       "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
+                       __FILE__, __PRETTY_FUNCTION__, source_str, group_str,
+                       old_iif->name, c_oil->oil.mfcc_parent, new_iif->name,
+                       input_iface_vif_index);
+       }
+
+       /* new iif loops to existing oif ? */
+       if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
+               struct interface *new_iif =
+                       pim_if_find_by_vif_index(input_iface_vif_index);
+
+               if (PIM_DEBUG_ZEBRA) {
+                       char source_str[INET_ADDRSTRLEN];
+                       char group_str[INET_ADDRSTRLEN];
+                       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
+                                      source_str, sizeof(source_str));
+                       pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
+                                      group_str, sizeof(group_str));
+                       zlog_debug(
+                               "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
+                               __FILE__, __PRETTY_FUNCTION__, source_str,
+                               group_str, new_iif->name,
+                               input_iface_vif_index);
+               }
+       }
+
+       /* update iif vif_index */
+       old_vif_index = c_oil->oil.mfcc_parent;
+       c_oil->oil.mfcc_parent = input_iface_vif_index;
+
+       /* update kernel multicast forwarding cache (MFC) */
+       if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) {
+               if (PIM_DEBUG_MROUTE) {
+                       /* just log warning */
+                       struct interface *old_iif =
+                               pim_if_find_by_vif_index(old_vif_index);
+                       struct interface *new_iif =
+                               pim_if_find_by_vif_index(input_iface_vif_index);
+                       char source_str[INET_ADDRSTRLEN];
+                       char group_str[INET_ADDRSTRLEN];
+                       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
+                                      source_str, sizeof(source_str));
+                       pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
+                                      group_str, sizeof(group_str));
+                       zlog_debug(
+                               "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
+                               __FILE__, __PRETTY_FUNCTION__, source_str,
+                               group_str,
+                               old_iif ? old_iif->name : "<old_iif?>",
+                               c_oil->oil.mfcc_parent,
+                               new_iif ? new_iif->name : "<new_iif?>",
+                               input_iface_vif_index);
+               }
+       }
 }
 
 void pim_scan_oil()
 {
-  struct listnode    *node;
-  struct listnode    *nextnode;
-  struct channel_oil *c_oil;
-  ifindex_t          ifindex;
-  int                vif_index = 0;
-
-  qpim_scan_oil_last = pim_time_monotonic_sec();
-  ++qpim_scan_oil_events;
-
-  for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil))
-    {
-      if (c_oil->up && c_oil->up->rpf.source_nexthop.interface)
-        {
-          ifindex = c_oil->up->rpf.source_nexthop.interface->ifindex;
-          vif_index = pim_if_find_vifindex_by_ifindex (ifindex);
-          /* Pass Current selected NH vif index to mroute download */
-          if (vif_index)
-            pim_scan_individual_oil (c_oil, vif_index);
-        }
-      else
-        pim_scan_individual_oil (c_oil, 0);
-    }
+       struct listnode *node;
+       struct listnode *nextnode;
+       struct channel_oil *c_oil;
+       ifindex_t ifindex;
+       int vif_index = 0;
+
+       qpim_scan_oil_last = pim_time_monotonic_sec();
+       ++qpim_scan_oil_events;
+
+       for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) {
+               if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
+                       ifindex = c_oil->up->rpf.source_nexthop
+                                         .interface->ifindex;
+                       vif_index = pim_if_find_vifindex_by_ifindex(ifindex);
+                       /* Pass Current selected NH vif index to mroute download
+                        */
+                       if (vif_index)
+                               pim_scan_individual_oil(c_oil, vif_index);
+               } else
+                       pim_scan_individual_oil(c_oil, 0);
+       }
 }
 
 static int on_rpf_cache_refresh(struct thread *t)
 {
-  /* update PIM protocol state */
-  scan_upstream_rpf_cache();
+       /* update PIM protocol state */
+       scan_upstream_rpf_cache();
 
-  /* update kernel multicast forwarding cache (MFC) */
-  pim_scan_oil();
+       /* update kernel multicast forwarding cache (MFC) */
+       pim_scan_oil();
 
-  qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
-  ++qpim_rpf_cache_refresh_events;
+       qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
+       ++qpim_rpf_cache_refresh_events;
 
-  //It is called as part of pim_neighbor_add
-  //pim_rp_setup ();
-  return 0;
+       // It is called as part of pim_neighbor_add
+       // pim_rp_setup ();
+       return 0;
 }
 
 void sched_rpf_cache_refresh(void)
 {
-  ++qpim_rpf_cache_refresh_requests;
+       ++qpim_rpf_cache_refresh_requests;
 
-  pim_rpf_set_refresh_time ();
+       pim_rpf_set_refresh_time();
 
-  if (qpim_rpf_cache_refresher) {
-    /* Refresh timer is already running */
-    return;
-  }
+       if (qpim_rpf_cache_refresher) {
+               /* Refresh timer is already running */
+               return;
+       }
 
-  /* Start refresh timer */
+       /* Start refresh timer */
 
-  if (PIM_DEBUG_ZEBRA) {
-    zlog_debug("%s: triggering %ld msec timer",
-               __PRETTY_FUNCTION__,
-               qpim_rpf_cache_refresh_delay_msec);
-  }
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__,
+                          qpim_rpf_cache_refresh_delay_msec);
+       }
 
-  thread_add_timer_msec(master, on_rpf_cache_refresh, 0,
-                        qpim_rpf_cache_refresh_delay_msec,
-                        &qpim_rpf_cache_refresher);
+       thread_add_timer_msec(master, on_rpf_cache_refresh, 0,
+                             qpim_rpf_cache_refresh_delay_msec,
+                             &qpim_rpf_cache_refresher);
 }
 
-static void
-pim_zebra_connected (struct zclient *zclient)
+static void pim_zebra_connected(struct zclient *zclient)
 {
-  /* Send the client registration */
-  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       /* Send the client registration */
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
 
-  zclient_send_reg_requests (zclient, VRF_DEFAULT);
+       zclient_send_reg_requests(zclient, VRF_DEFAULT);
 }
 
 void pim_zebra_init(void)
 {
-  int i;
+       int i;
 
 #ifdef HAVE_TCP_ZEBRA
-  zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT);
+       zlog_notice(
+               "zclient update contacting ZEBRA daemon at socket TCP %s,%d",
+               "127.0.0.1", ZEBRA_PORT);
 #else
-  zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get());
+       zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s",
+                   zclient_serv_path_get());
 #endif
 
-  /* Socket for receiving updates from Zebra daemon */
-  zclient = zclient_new (master);
-
-  zclient->zebra_connected          = pim_zebra_connected;
-  zclient->router_id_update         = pim_router_id_update_zebra;
-  zclient->interface_add            = pim_zebra_if_add;
-  zclient->interface_delete         = pim_zebra_if_del;
-  zclient->interface_up             = pim_zebra_if_state_up;
-  zclient->interface_down           = pim_zebra_if_state_down;
-  zclient->interface_address_add    = pim_zebra_if_address_add;
-  zclient->interface_address_delete = pim_zebra_if_address_del;
-  zclient->nexthop_update           = pim_parse_nexthop_update;
-
-  zclient_init(zclient, ZEBRA_ROUTE_PIM, 0);
-  if (PIM_DEBUG_PIM_TRACE) {
-    zlog_info("zclient_init cleared redistribution request");
-  }
-
-  zassert(zclient->redist_default == ZEBRA_ROUTE_PIM);
-
-  /* Request all redistribution */
-  for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
-    if (i == zclient->redist_default)
-      continue;
-    vrf_bitmap_set (zclient->redist[AFI_IP][i], VRF_DEFAULT);;
-    if (PIM_DEBUG_PIM_TRACE) {
-      zlog_debug("%s: requesting redistribution for %s (%i)", 
-                __PRETTY_FUNCTION__, zebra_route_string(i), i);
-    }
-  }
-
-  /* Request default information */
-  zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
-                               zclient, VRF_DEFAULT);
-  
-  if (PIM_DEBUG_PIM_TRACE) {
-    zlog_info("%s: requesting default information redistribution",
-             __PRETTY_FUNCTION__);
-
-    zlog_notice("%s: zclient update socket initialized",
-               __PRETTY_FUNCTION__);
-  }
-
-  zclient_lookup_new();
+       /* Socket for receiving updates from Zebra daemon */
+       zclient = zclient_new(master);
+
+       zclient->zebra_connected = pim_zebra_connected;
+       zclient->router_id_update = pim_router_id_update_zebra;
+       zclient->interface_add = pim_zebra_if_add;
+       zclient->interface_delete = pim_zebra_if_del;
+       zclient->interface_up = pim_zebra_if_state_up;
+       zclient->interface_down = pim_zebra_if_state_down;
+       zclient->interface_address_add = pim_zebra_if_address_add;
+       zclient->interface_address_delete = pim_zebra_if_address_del;
+       zclient->nexthop_update = pim_parse_nexthop_update;
+
+       zclient_init(zclient, ZEBRA_ROUTE_PIM, 0);
+       if (PIM_DEBUG_PIM_TRACE) {
+               zlog_info("zclient_init cleared redistribution request");
+       }
+
+       zassert(zclient->redist_default == ZEBRA_ROUTE_PIM);
+
+       /* Request all redistribution */
+       for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+               if (i == zclient->redist_default)
+                       continue;
+               vrf_bitmap_set(zclient->redist[AFI_IP][i], VRF_DEFAULT);
+               ;
+               if (PIM_DEBUG_PIM_TRACE) {
+                       zlog_debug("%s: requesting redistribution for %s (%i)",
+                                  __PRETTY_FUNCTION__, zebra_route_string(i),
+                                  i);
+               }
+       }
+
+       /* Request default information */
+       zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
+                                    VRF_DEFAULT);
+
+       if (PIM_DEBUG_PIM_TRACE) {
+               zlog_info("%s: requesting default information redistribution",
+                         __PRETTY_FUNCTION__);
+
+               zlog_notice("%s: zclient update socket initialized",
+                           __PRETTY_FUNCTION__);
+       }
+
+       zclient_lookup_new();
 }
 
 void igmp_anysource_forward_start(struct igmp_group *group)
 {
-  struct igmp_source *source;
-  struct in_addr src_addr = { .s_addr = 0 };
-  /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
-  zassert(group->group_filtermode_isexcl);
-  zassert(listcount(group->group_source_list) < 1);
-
-  source = source_new (group, src_addr);
-  if (!source)
-    {
-      zlog_warn ("%s: Failure to create * source", __PRETTY_FUNCTION__);
-      return;
-    }
-
-  igmp_source_forward_start (source);
+       struct igmp_source *source;
+       struct in_addr src_addr = {.s_addr = 0};
+       /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
+       zassert(group->group_filtermode_isexcl);
+       zassert(listcount(group->group_source_list) < 1);
+
+       source = source_new(group, src_addr);
+       if (!source) {
+               zlog_warn("%s: Failure to create * source",
+                         __PRETTY_FUNCTION__);
+               return;
+       }
+
+       igmp_source_forward_start(source);
 }
 
 void igmp_anysource_forward_stop(struct igmp_group *group)
 {
-  struct igmp_source *source;
-  struct in_addr star = { .s_addr = 0 };
+       struct igmp_source *source;
+       struct in_addr star = {.s_addr = 0};
 
-  source = igmp_find_source_by_addr (group, star);
-  if (source)
-    igmp_source_forward_stop (source);
+       source = igmp_find_source_by_addr(group, star);
+       if (source)
+               igmp_source_forward_stop(source);
 }
 
-static void
-igmp_source_forward_reevaluate_one(struct igmp_source *source)
+static void igmp_source_forward_reevaluate_one(struct igmp_source *source)
 {
-  struct prefix_sg sg;
-  struct igmp_group *group = source->source_group;
-  struct pim_ifchannel *ch;
-
-  if ((source->source_addr.s_addr != INADDR_ANY) ||
-      !IGMP_SOURCE_TEST_FORWARDING (source->source_flags))
-    return;
-
-  memset (&sg, 0, sizeof (struct prefix_sg));
-  sg.src = source->source_addr;
-  sg.grp = group->group_addr;
-
-  ch = pim_ifchannel_find (group->group_igmp_sock->interface, &sg);
-  if (pim_is_grp_ssm (group->group_addr))
-    {
-      /* If SSM group withdraw local membership */
-      if (ch && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE))
-        {
-          if (PIM_DEBUG_PIM_EVENTS)
-            zlog_debug ("local membership del for %s as G is now SSM",
-                        pim_str_sg_dump (&sg));
-          pim_ifchannel_local_membership_del (group->group_igmp_sock->interface, &sg);
-        }
-    }
-  else
-    {
-      /* If ASM group add local membership */
-      if (!ch || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO))
-        {
-          if (PIM_DEBUG_PIM_EVENTS)
-            zlog_debug ("local membership add for %s as G is now ASM",
-                        pim_str_sg_dump (&sg));
-          pim_ifchannel_local_membership_add (group->group_igmp_sock->interface, &sg);
-        }
-    }
+       struct prefix_sg sg;
+       struct igmp_group *group = source->source_group;
+       struct pim_ifchannel *ch;
+
+       if ((source->source_addr.s_addr != INADDR_ANY)
+           || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags))
+               return;
+
+       memset(&sg, 0, sizeof(struct prefix_sg));
+       sg.src = source->source_addr;
+       sg.grp = group->group_addr;
+
+       ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg);
+       if (pim_is_grp_ssm(group->group_addr)) {
+               /* If SSM group withdraw local membership */
+               if (ch
+                   && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) {
+                       if (PIM_DEBUG_PIM_EVENTS)
+                               zlog_debug(
+                                       "local membership del for %s as G is now SSM",
+                                       pim_str_sg_dump(&sg));
+                       pim_ifchannel_local_membership_del(
+                               group->group_igmp_sock->interface, &sg);
+               }
+       } else {
+               /* If ASM group add local membership */
+               if (!ch
+                   || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) {
+                       if (PIM_DEBUG_PIM_EVENTS)
+                               zlog_debug(
+                                       "local membership add for %s as G is now ASM",
+                                       pim_str_sg_dump(&sg));
+                       pim_ifchannel_local_membership_add(
+                               group->group_igmp_sock->interface, &sg);
+               }
+       }
 }
 
-void
-igmp_source_forward_reevaluate_all(void)
+void igmp_source_forward_reevaluate_all(void)
 {
-  struct listnode *ifnode;
-  struct interface *ifp;
-
-  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp))
-    {
-      struct pim_interface *pim_ifp = ifp->info;
-      struct listnode  *sock_node;
-      struct igmp_sock *igmp;
-
-      if (!pim_ifp)
-        continue;
-
-      /* scan igmp sockets */
-      for (ALL_LIST_ELEMENTS_RO (pim_ifp->igmp_socket_list, sock_node, igmp))
-        {
-          struct listnode *grpnode;
-          struct igmp_group *grp;
-
-          /* scan igmp groups */
-          for (ALL_LIST_ELEMENTS_RO (igmp->igmp_group_list, grpnode, grp))
-            {
-              struct listnode    *srcnode;
-              struct igmp_source *src;
-
-              /* scan group sources */
-              for (ALL_LIST_ELEMENTS_RO (grp->group_source_list,
-                                        srcnode, src))
-                {
-                  igmp_source_forward_reevaluate_one (src);
-                } /* scan group sources */
-            } /* scan igmp groups */
-        } /* scan igmp sockets */
-    } /* scan interfaces */
+       struct listnode *ifnode;
+       struct interface *ifp;
+
+       for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) {
+               struct pim_interface *pim_ifp = ifp->info;
+               struct listnode *sock_node;
+               struct igmp_sock *igmp;
+
+               if (!pim_ifp)
+                       continue;
+
+               /* scan igmp sockets */
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
+                                         igmp)) {
+                       struct listnode *grpnode;
+                       struct igmp_group *grp;
+
+                       /* scan igmp groups */
+                       for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
+                                                 grpnode, grp)) {
+                               struct listnode *srcnode;
+                               struct igmp_source *src;
+
+                               /* scan group sources */
+                               for (ALL_LIST_ELEMENTS_RO(
+                                            grp->group_source_list, srcnode,
+                                            src)) {
+                                       igmp_source_forward_reevaluate_one(src);
+                               } /* scan group sources */
+                       }        /* scan igmp groups */
+               }                 /* scan igmp sockets */
+       }                         /* scan interfaces */
 }
 
 void igmp_source_forward_start(struct igmp_source *source)
 {
-  struct igmp_group *group;
-  struct prefix_sg sg;
-  int result;
-  int input_iface_vif_index = 0;
-
-  memset (&sg, 0, sizeof (struct prefix_sg));
-  sg.src = source->source_addr;
-  sg.grp = source->source_group->group_addr;
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
-              __PRETTY_FUNCTION__,
-              pim_str_sg_dump (&sg),
-              source->source_group->group_igmp_sock->fd,
-              source->source_group->group_igmp_sock->interface->name,
-              IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
-  }
-
-  /* Prevent IGMP interface from installing multicast route multiple
-     times */
-  if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
-    return;
-  }
-
-  group = source->source_group;
-
-  if (!source->source_channel_oil) {
-    struct in_addr vif_source;
-    struct pim_interface *pim_oif;
-    struct prefix nht_p, src, grp;
-    int ret = 0;
-    struct pim_nexthop_cache out_pnc;
-    struct pim_nexthop nexthop;
-    struct pim_upstream *up = NULL;
-
-    if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp))
-      return;
-
-    /* Register addr with Zebra NHT */
-    nht_p.family = AF_INET;
-    nht_p.prefixlen = IPV4_MAX_BITLEN;
-    nht_p.u.prefix4 = vif_source;
-    memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
-
-    src.family = AF_INET;
-    src.prefixlen = IPV4_MAX_BITLEN;
-    src.u.prefix4 = vif_source;   //RP or Src address
-    grp.family = AF_INET;
-    grp.prefixlen = IPV4_MAX_BITLEN;
-    grp.u.prefix4 = sg.grp;
-
-    if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
-      {
-        if (out_pnc.nexthop_num)
-          {
-            up = pim_upstream_find (&sg);
-            memset (&nexthop, 0, sizeof (struct pim_nexthop));
-            if (up)
-              memcpy (&nexthop, &up->rpf.source_nexthop, sizeof (struct pim_nexthop));
-            //Compute PIM RPF using Cached nexthop
-            pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0);
-            if (nexthop.interface)
-              input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex);
-          }
-        else
-          {
-            if (PIM_DEBUG_ZEBRA)
-              {
-                char buf1[INET_ADDRSTRLEN];
-                char buf2[INET_ADDRSTRLEN];
-                pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1));
-                pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2));
-                zlog_debug ("%s: NHT Nexthop not found for addr %s grp %s" ,
-                          __PRETTY_FUNCTION__, buf1, buf2);
-              }
-          }
-      }
-    else
-      input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp);
-
-    if (PIM_DEBUG_ZEBRA)
-      {
-        char buf2[INET_ADDRSTRLEN];
-        pim_inet4_dump("<source?>", vif_source, buf2, sizeof(buf2));
-        zlog_debug ("%s: NHT %s vif_source %s vif_index:%d ", __PRETTY_FUNCTION__,
-            pim_str_sg_dump (&sg), buf2, input_iface_vif_index);
-      }
-
-    if (input_iface_vif_index < 1) {
-      if (PIM_DEBUG_IGMP_TRACE)
-       {
-         char source_str[INET_ADDRSTRLEN];
-         pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
-         zlog_debug("%s %s: could not find input interface for source %s",
-                    __FILE__, __PRETTY_FUNCTION__,
-                    source_str);
+       struct igmp_group *group;
+       struct prefix_sg sg;
+       int result;
+       int input_iface_vif_index = 0;
+
+       memset(&sg, 0, sizeof(struct prefix_sg));
+       sg.src = source->source_addr;
+       sg.grp = source->source_group->group_addr;
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               zlog_debug(
+                       "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
+                       __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
+                       source->source_group->group_igmp_sock->fd,
+                       source->source_group->group_igmp_sock->interface->name,
+                       IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
+       }
+
+       /* Prevent IGMP interface from installing multicast route multiple
+          times */
+       if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
+               return;
        }
-      return;
-    }
-
-    /*
-      Protect IGMP against adding looped MFC entries created by both
-      source and receiver attached to the same interface. See TODO
-      T22.
-    */
-    pim_oif = source->source_group->group_igmp_sock->interface->info;
-    if (!pim_oif) {
-      if (PIM_DEBUG_IGMP_TRACE)
-       {
-         zlog_debug("%s: multicast not enabled on oif=%s ?",
-                    __PRETTY_FUNCTION__,
-                    source->source_group->group_igmp_sock->interface->name);
+
+       group = source->source_group;
+
+       if (!source->source_channel_oil) {
+               struct in_addr vif_source;
+               struct pim_interface *pim_oif;
+               struct prefix nht_p, src, grp;
+               int ret = 0;
+               struct pim_nexthop_cache out_pnc;
+               struct pim_nexthop nexthop;
+               struct pim_upstream *up = NULL;
+
+               if (!pim_rp_set_upstream_addr(&vif_source, source->source_addr,
+                                             sg.grp))
+                       return;
+
+               /* Register addr with Zebra NHT */
+               nht_p.family = AF_INET;
+               nht_p.prefixlen = IPV4_MAX_BITLEN;
+               nht_p.u.prefix4 = vif_source;
+               memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
+
+               src.family = AF_INET;
+               src.prefixlen = IPV4_MAX_BITLEN;
+               src.u.prefix4 = vif_source; // RP or Src address
+               grp.family = AF_INET;
+               grp.prefixlen = IPV4_MAX_BITLEN;
+               grp.u.prefix4 = sg.grp;
+
+               if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL,
+                                                    &out_pnc))
+                   == 1) {
+                       if (out_pnc.nexthop_num) {
+                               up = pim_upstream_find(&sg);
+                               memset(&nexthop, 0, sizeof(struct pim_nexthop));
+                               if (up)
+                                       memcpy(&nexthop,
+                                              &up->rpf.source_nexthop,
+                                              sizeof(struct pim_nexthop));
+                               // Compute PIM RPF using Cached nexthop
+                               pim_ecmp_nexthop_search(&out_pnc, &nexthop,
+                                                       &src, &grp, 0);
+                               if (nexthop.interface)
+                                       input_iface_vif_index =
+                                               pim_if_find_vifindex_by_ifindex(
+                                                       nexthop.interface->ifindex);
+                       } else {
+                               if (PIM_DEBUG_ZEBRA) {
+                                       char buf1[INET_ADDRSTRLEN];
+                                       char buf2[INET_ADDRSTRLEN];
+                                       pim_inet4_dump("<source?>",
+                                                      nht_p.u.prefix4, buf1,
+                                                      sizeof(buf1));
+                                       pim_inet4_dump("<source?>",
+                                                      grp.u.prefix4, buf2,
+                                                      sizeof(buf2));
+                                       zlog_debug(
+                                               "%s: NHT Nexthop not found for addr %s grp %s",
+                                               __PRETTY_FUNCTION__, buf1,
+                                               buf2);
+                               }
+                       }
+               } else
+                       input_iface_vif_index =
+                               pim_ecmp_fib_lookup_if_vif_index(vif_source,
+                                                                &src, &grp);
+
+               if (PIM_DEBUG_ZEBRA) {
+                       char buf2[INET_ADDRSTRLEN];
+                       pim_inet4_dump("<source?>", vif_source, buf2,
+                                      sizeof(buf2));
+                       zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
+                                  __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
+                                  buf2, input_iface_vif_index);
+               }
+
+               if (input_iface_vif_index < 1) {
+                       if (PIM_DEBUG_IGMP_TRACE) {
+                               char source_str[INET_ADDRSTRLEN];
+                               pim_inet4_dump("<source?>", source->source_addr,
+                                              source_str, sizeof(source_str));
+                               zlog_debug(
+                                       "%s %s: could not find input interface for source %s",
+                                       __FILE__, __PRETTY_FUNCTION__,
+                                       source_str);
+                       }
+                       return;
+               }
+
+               /*
+                 Protect IGMP against adding looped MFC entries created by both
+                 source and receiver attached to the same interface. See TODO
+                 T22.
+               */
+               pim_oif =
+                       source->source_group->group_igmp_sock->interface->info;
+               if (!pim_oif) {
+                       if (PIM_DEBUG_IGMP_TRACE) {
+                               zlog_debug(
+                                       "%s: multicast not enabled on oif=%s ?",
+                                       __PRETTY_FUNCTION__,
+                                       source->source_group->group_igmp_sock
+                                               ->interface->name);
+                       }
+                       return;
+               }
+
+               if (input_iface_vif_index == pim_oif->mroute_vif_index) {
+                       /* ignore request for looped MFC entry */
+                       if (PIM_DEBUG_IGMP_TRACE) {
+                               zlog_debug(
+                                       "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
+                                       __PRETTY_FUNCTION__,
+                                       pim_str_sg_dump(&sg),
+                                       source->source_group->group_igmp_sock
+                                               ->fd,
+                                       source->source_group->group_igmp_sock
+                                               ->interface->name,
+                                       input_iface_vif_index);
+                       }
+                       return;
+               }
+
+               source->source_channel_oil =
+                       pim_channel_oil_add(&sg, input_iface_vif_index);
+               if (!source->source_channel_oil) {
+                       if (PIM_DEBUG_IGMP_TRACE) {
+                               zlog_debug(
+                                       "%s %s: could not create OIL for channel (S,G)=%s",
+                                       __FILE__, __PRETTY_FUNCTION__,
+                                       pim_str_sg_dump(&sg));
+                       }
+                       return;
+               }
        }
-      return;
-    }
-
-    if (input_iface_vif_index == pim_oif->mroute_vif_index) {
-      /* ignore request for looped MFC entry */
-      if (PIM_DEBUG_IGMP_TRACE) {
-       zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
-                  __PRETTY_FUNCTION__,
-                  pim_str_sg_dump (&sg),
-                  source->source_group->group_igmp_sock->fd,
-                  source->source_group->group_igmp_sock->interface->name,
-                  input_iface_vif_index);
-      }
-      return;
-    }
-
-    source->source_channel_oil = pim_channel_oil_add(&sg,
-                                                    input_iface_vif_index);
-    if (!source->source_channel_oil) {
-      if (PIM_DEBUG_IGMP_TRACE)
-       {
-         zlog_debug("%s %s: could not create OIL for channel (S,G)=%s",
-                   __FILE__, __PRETTY_FUNCTION__,
-                   pim_str_sg_dump (&sg));
+
+       result = pim_channel_add_oif(source->source_channel_oil,
+                                    group->group_igmp_sock->interface,
+                                    PIM_OIF_FLAG_PROTO_IGMP);
+       if (result) {
+               if (PIM_DEBUG_MROUTE) {
+                       zlog_warn("%s: add_oif() failed with return=%d",
+                                 __func__, result);
+               }
+               return;
        }
-      return;
-    }
-  }
-
-  result = pim_channel_add_oif(source->source_channel_oil,
-                              group->group_igmp_sock->interface,
-                              PIM_OIF_FLAG_PROTO_IGMP);
-  if (result) {
-    if (PIM_DEBUG_MROUTE)
-      {
-        zlog_warn("%s: add_oif() failed with return=%d",
-                  __func__, result);
-      }
-    return;
-  }
-
-  /*
-    Feed IGMPv3-gathered local membership information into PIM
-    per-interface (S,G) state.
-   */
-  if (!pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg))
-    {
-      if (PIM_DEBUG_MROUTE)
-       zlog_warn ("%s: Failure to add local membership for %s",
-                  __PRETTY_FUNCTION__, pim_str_sg_dump (&sg));
-      return;
-    }
-
-  IGMP_SOURCE_DO_FORWARDING(source->source_flags);
+
+       /*
+         Feed IGMPv3-gathered local membership information into PIM
+         per-interface (S,G) state.
+        */
+       if (!pim_ifchannel_local_membership_add(
+                   group->group_igmp_sock->interface, &sg)) {
+               if (PIM_DEBUG_MROUTE)
+                       zlog_warn("%s: Failure to add local membership for %s",
+                                 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
+               return;
+       }
+
+       IGMP_SOURCE_DO_FORWARDING(source->source_flags);
 }
 
 /*
@@ -966,203 +1010,219 @@ void igmp_source_forward_start(struct igmp_source *source)
  */
 void igmp_source_forward_stop(struct igmp_source *source)
 {
-  struct igmp_group *group;
-  struct prefix_sg sg;
-  int result;
-
-  memset (&sg, 0, sizeof (struct prefix_sg));
-  sg.src = source->source_addr;
-  sg.grp = source->source_group->group_addr;
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
-              __PRETTY_FUNCTION__,
-              pim_str_sg_dump (&sg),
-              source->source_group->group_igmp_sock->fd,
-              source->source_group->group_igmp_sock->interface->name,
-              IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
-  }
-
-  /* Prevent IGMP interface from removing multicast route multiple
-     times */
-  if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
-    return;
-  }
-
-  group = source->source_group;
-
-  /*
-   It appears that in certain circumstances that 
-   igmp_source_forward_stop is called when IGMP forwarding
-   was not enabled in oif_flags for this outgoing interface.
-   Possibly because of multiple calls. When that happens, we
-   enter the below if statement and this function returns early
-   which in turn triggers the calling function to assert.
-   Making the call to pim_channel_del_oif and ignoring the return code
-   fixes the issue without ill effect, similar to
-   pim_forward_stop below.
-  */
-  result = pim_channel_del_oif(source->source_channel_oil,
-                               group->group_igmp_sock->interface,
-                               PIM_OIF_FLAG_PROTO_IGMP);
-  if (result) {
-    if (PIM_DEBUG_IGMP_TRACE)
-      zlog_debug("%s: pim_channel_del_oif() failed with return=%d",
-                __func__, result);
-    return;
-  }
-
-  /*
-    Feed IGMPv3-gathered local membership information into PIM
-    per-interface (S,G) state.
-   */
-  pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
-                                    &sg);
-
-  IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
+       struct igmp_group *group;
+       struct prefix_sg sg;
+       int result;
+
+       memset(&sg, 0, sizeof(struct prefix_sg));
+       sg.src = source->source_addr;
+       sg.grp = source->source_group->group_addr;
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               zlog_debug(
+                       "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
+                       __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
+                       source->source_group->group_igmp_sock->fd,
+                       source->source_group->group_igmp_sock->interface->name,
+                       IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
+       }
+
+       /* Prevent IGMP interface from removing multicast route multiple
+          times */
+       if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
+               return;
+       }
+
+       group = source->source_group;
+
+       /*
+        It appears that in certain circumstances that
+        igmp_source_forward_stop is called when IGMP forwarding
+        was not enabled in oif_flags for this outgoing interface.
+        Possibly because of multiple calls. When that happens, we
+        enter the below if statement and this function returns early
+        which in turn triggers the calling function to assert.
+        Making the call to pim_channel_del_oif and ignoring the return code
+        fixes the issue without ill effect, similar to
+        pim_forward_stop below.
+       */
+       result = pim_channel_del_oif(source->source_channel_oil,
+                                    group->group_igmp_sock->interface,
+                                    PIM_OIF_FLAG_PROTO_IGMP);
+       if (result) {
+               if (PIM_DEBUG_IGMP_TRACE)
+                       zlog_debug(
+                               "%s: pim_channel_del_oif() failed with return=%d",
+                               __func__, result);
+               return;
+       }
+
+       /*
+         Feed IGMPv3-gathered local membership information into PIM
+         per-interface (S,G) state.
+        */
+       pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
+                                          &sg);
+
+       IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
 }
 
 void pim_forward_start(struct pim_ifchannel *ch)
 {
-  struct pim_upstream *up = ch->upstream;
-  uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
-  int input_iface_vif_index =  0;
-
-  if (PIM_DEBUG_PIM_TRACE) {
-    char source_str[INET_ADDRSTRLEN];
-    char group_str[INET_ADDRSTRLEN];
-    char upstream_str[INET_ADDRSTRLEN];
-
-    pim_inet4_dump("<source?>", ch->sg.src, source_str, sizeof(source_str));
-    pim_inet4_dump("<group?>", ch->sg.grp, group_str, sizeof(group_str));
-    pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, sizeof(upstream_str));
-    zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)",
-              __PRETTY_FUNCTION__,
-              source_str, group_str, ch->interface->name, upstream_str);
-  }
-
-  /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
-     as part of mroute_del called by pim_forward_stop.
-  */
-  if (!up->channel_oil ||
-      (up->channel_oil && up->channel_oil->oil.mfcc_parent >= MAXVIFS))
-    {
-      struct prefix nht_p, src, grp;
-      int ret = 0;
-      struct pim_nexthop_cache out_pnc;
-
-      /* Register addr with Zebra NHT */
-      nht_p.family = AF_INET;
-      nht_p.prefixlen = IPV4_MAX_BITLEN;
-      nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
-      grp.family = AF_INET;
-      grp.prefixlen = IPV4_MAX_BITLEN;
-      grp.u.prefix4 = up->sg.grp;
-      memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
-
-      if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
-        {
-          if (out_pnc.nexthop_num)
-            {
-              src.family = AF_INET;
-              src.prefixlen = IPV4_MAX_BITLEN;
-              src.u.prefix4 = up->upstream_addr; //RP or Src address
-              grp.family = AF_INET;
-              grp.prefixlen = IPV4_MAX_BITLEN;
-              grp.u.prefix4 = up->sg.grp;
-              //Compute PIM RPF using Cached nexthop
-              if (pim_ecmp_nexthop_search (&out_pnc, &up->rpf.source_nexthop, &src, &grp, 0) == 0)
-                input_iface_vif_index = pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop.interface->ifindex);
-              else
-                {
-                  if (PIM_DEBUG_TRACE)
-                    zlog_debug ("%s: Nexthop selection failed for %s ", __PRETTY_FUNCTION__, up->sg_str);
-                }
-            }
-          else
-            {
-              if (PIM_DEBUG_ZEBRA)
-                {
-                  char buf1[INET_ADDRSTRLEN];
-                  char buf2[INET_ADDRSTRLEN];
-                  pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1));
-                  pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2));
-                  zlog_debug ("%s: NHT pnc is NULL for addr %s grp %s" ,
-                          __PRETTY_FUNCTION__, buf1, buf2);
-                }
-            }
-        }
-      else
-        input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(up->upstream_addr, &src, &grp);
-
-      if (input_iface_vif_index < 1)
-        {
-          if (PIM_DEBUG_PIM_TRACE)
-            {
-              char source_str[INET_ADDRSTRLEN];
-              pim_inet4_dump("<source?>", up->sg.src, source_str, sizeof(source_str));
-              zlog_debug("%s %s: could not find input interface for source %s",
-                      __FILE__, __PRETTY_FUNCTION__,
-                      source_str);
-            }
-          return;
-        }
-      if (PIM_DEBUG_TRACE)
-        {
-          struct interface *in_intf = pim_if_find_by_vif_index (input_iface_vif_index);
-          zlog_debug ("%s: Update channel_oil IIF %s VIFI %d entry %s ",
-                      __PRETTY_FUNCTION__, in_intf ? in_intf->name : "NIL",
-                      input_iface_vif_index, up->sg_str);
-        }
-      up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index);
-      if (!up->channel_oil)
-        {
-          if (PIM_DEBUG_PIM_TRACE)
-            zlog_debug ("%s %s: could not create OIL for channel (S,G)=%s",
-                        __FILE__, __PRETTY_FUNCTION__, up->sg_str);
-          return;
-        }
-    }
-
-  if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
-    mask = PIM_OIF_FLAG_PROTO_IGMP;
-
-  pim_channel_add_oif (up->channel_oil, ch->interface, mask);
+       struct pim_upstream *up = ch->upstream;
+       uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
+       int input_iface_vif_index = 0;
+
+       if (PIM_DEBUG_PIM_TRACE) {
+               char source_str[INET_ADDRSTRLEN];
+               char group_str[INET_ADDRSTRLEN];
+               char upstream_str[INET_ADDRSTRLEN];
+
+               pim_inet4_dump("<source?>", ch->sg.src, source_str,
+                              sizeof(source_str));
+               pim_inet4_dump("<group?>", ch->sg.grp, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str,
+                              sizeof(upstream_str));
+               zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
+                          source_str, group_str, ch->interface->name,
+                          upstream_str);
+       }
+
+       /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
+          as part of mroute_del called by pim_forward_stop.
+       */
+       if (!up->channel_oil
+           || (up->channel_oil
+               && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) {
+               struct prefix nht_p, src, grp;
+               int ret = 0;
+               struct pim_nexthop_cache out_pnc;
+
+               /* Register addr with Zebra NHT */
+               nht_p.family = AF_INET;
+               nht_p.prefixlen = IPV4_MAX_BITLEN;
+               nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+               grp.family = AF_INET;
+               grp.prefixlen = IPV4_MAX_BITLEN;
+               grp.u.prefix4 = up->sg.grp;
+               memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
+
+               if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL,
+                                                    &out_pnc))
+                   == 1) {
+                       if (out_pnc.nexthop_num) {
+                               src.family = AF_INET;
+                               src.prefixlen = IPV4_MAX_BITLEN;
+                               src.u.prefix4 =
+                                       up->upstream_addr; // RP or Src address
+                               grp.family = AF_INET;
+                               grp.prefixlen = IPV4_MAX_BITLEN;
+                               grp.u.prefix4 = up->sg.grp;
+                               // Compute PIM RPF using Cached nexthop
+                               if (pim_ecmp_nexthop_search(
+                                           &out_pnc, &up->rpf.source_nexthop,
+                                           &src, &grp, 0)
+                                   == 0)
+                                       input_iface_vif_index =
+                                               pim_if_find_vifindex_by_ifindex(
+                                                       up->rpf.source_nexthop
+                                                               .interface->ifindex);
+                               else {
+                                       if (PIM_DEBUG_TRACE)
+                                               zlog_debug(
+                                                       "%s: Nexthop selection failed for %s ",
+                                                       __PRETTY_FUNCTION__,
+                                                       up->sg_str);
+                               }
+                       } else {
+                               if (PIM_DEBUG_ZEBRA) {
+                                       char buf1[INET_ADDRSTRLEN];
+                                       char buf2[INET_ADDRSTRLEN];
+                                       pim_inet4_dump("<source?>",
+                                                      nht_p.u.prefix4, buf1,
+                                                      sizeof(buf1));
+                                       pim_inet4_dump("<source?>",
+                                                      grp.u.prefix4, buf2,
+                                                      sizeof(buf2));
+                                       zlog_debug(
+                                               "%s: NHT pnc is NULL for addr %s grp %s",
+                                               __PRETTY_FUNCTION__, buf1,
+                                               buf2);
+                               }
+                       }
+               } else
+                       input_iface_vif_index =
+                               pim_ecmp_fib_lookup_if_vif_index(
+                                       up->upstream_addr, &src, &grp);
+
+               if (input_iface_vif_index < 1) {
+                       if (PIM_DEBUG_PIM_TRACE) {
+                               char source_str[INET_ADDRSTRLEN];
+                               pim_inet4_dump("<source?>", up->sg.src,
+                                              source_str, sizeof(source_str));
+                               zlog_debug(
+                                       "%s %s: could not find input interface for source %s",
+                                       __FILE__, __PRETTY_FUNCTION__,
+                                       source_str);
+                       }
+                       return;
+               }
+               if (PIM_DEBUG_TRACE) {
+                       struct interface *in_intf =
+                               pim_if_find_by_vif_index(input_iface_vif_index);
+                       zlog_debug(
+                               "%s: Update channel_oil IIF %s VIFI %d entry %s ",
+                               __PRETTY_FUNCTION__,
+                               in_intf ? in_intf->name : "NIL",
+                               input_iface_vif_index, up->sg_str);
+               }
+               up->channel_oil =
+                       pim_channel_oil_add(&up->sg, input_iface_vif_index);
+               if (!up->channel_oil) {
+                       if (PIM_DEBUG_PIM_TRACE)
+                               zlog_debug(
+                                       "%s %s: could not create OIL for channel (S,G)=%s",
+                                       __FILE__, __PRETTY_FUNCTION__,
+                                       up->sg_str);
+                       return;
+               }
+       }
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+               mask = PIM_OIF_FLAG_PROTO_IGMP;
+
+       pim_channel_add_oif(up->channel_oil, ch->interface, mask);
 }
 
 void pim_forward_stop(struct pim_ifchannel *ch)
 {
-  struct pim_upstream *up = ch->upstream;
+       struct pim_upstream *up = ch->upstream;
 
-  if (PIM_DEBUG_PIM_TRACE) {
-    zlog_debug("%s: (S,G)=%s oif=%s",
-              __PRETTY_FUNCTION__,
-              ch->sg_str, ch->interface->name);
-  }
+       if (PIM_DEBUG_PIM_TRACE) {
+               zlog_debug("%s: (S,G)=%s oif=%s", __PRETTY_FUNCTION__,
+                          ch->sg_str, ch->interface->name);
+       }
 
-  pim_channel_del_oif(up->channel_oil,
-                      ch->interface,
-                      PIM_OIF_FLAG_PROTO_PIM);
+       pim_channel_del_oif(up->channel_oil, ch->interface,
+                           PIM_OIF_FLAG_PROTO_PIM);
 }
 
-void
-pim_zebra_zclient_update (struct vty *vty)
+void pim_zebra_zclient_update(struct vty *vty)
 {
-  vty_out(vty, "Zclient update socket: ");
-
-  if (zclient) {
-    vty_out (vty, "%d failures=%d\n", zclient->sock,
-           zclient->fail);
-  }
-  else {
-    vty_out (vty, "<null zclient>\n");
-  }
+       vty_out(vty, "Zclient update socket: ");
+
+       if (zclient) {
+               vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
+       } else {
+               vty_out(vty, "<null zclient>\n");
+       }
 }
 
-struct zclient *pim_zebra_zclient_get (void)
+struct zclient *pim_zebra_zclient_get(void)
 {
-  if (zclient)
-    return zclient;
-  else
-    return NULL;
+       if (zclient)
+               return zclient;
+       else
+               return NULL;
 }