diff options
Diffstat (limited to 'pimd/pim_nht.c')
| -rw-r--r-- | pimd/pim_nht.c | 1949 | 
1 files changed, 973 insertions, 976 deletions
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 4aa6ecd5f3..f8bf2ac77c 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -44,258 +44,247 @@   * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister   *   command to Zebra.   */ -void -pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, -                       int command) +void pim_sendmsg_zebra_rnh(struct zclient *zclient, +			   struct pim_nexthop_cache *pnc, int command)  { -  struct stream *s; -  struct prefix *p; -  int ret; - -  /* Check socket. */ -  if (!zclient || zclient->sock < 0) -    return; - -  p = &(pnc->rpf.rpf_addr); -  s = zclient->obuf; -  stream_reset (s); -  zclient_create_header (s, command, VRF_DEFAULT); -  /* get update for all routes for a prefix */ -  stream_putc (s, 0); - -  stream_putw (s, PREFIX_FAMILY (p)); -  stream_putc (s, p->prefixlen); -  switch (PREFIX_FAMILY (p)) -    { -    case AF_INET: -      stream_put_in_addr (s, &p->u.prefix4); -      break; -    case AF_INET6: -      stream_put (s, &(p->u.prefix6), 16); -      break; -    default: -      break; -    } -  stream_putw_at (s, 0, stream_get_endp (s)); - -  ret = zclient_send_message (zclient); -  if (ret < 0) -    zlog_warn ("sendmsg_nexthop: zclient_send_message() failed"); - - -  if (PIM_DEBUG_TRACE) -    { -      char buf[PREFIX2STR_BUFFER]; -      prefix2str (p, buf, sizeof (buf)); -      zlog_debug ("%s: NHT %sregistered addr %s with Zebra ret:%d ", -                  __PRETTY_FUNCTION__, -                  (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", buf, ret); -    } - -  return; +	struct stream *s; +	struct prefix *p; +	int ret; + +	/* Check socket. */ +	if (!zclient || zclient->sock < 0) +		return; + +	p = &(pnc->rpf.rpf_addr); +	s = zclient->obuf; +	stream_reset(s); +	zclient_create_header(s, command, VRF_DEFAULT); +	/* get update for all routes for a prefix */ +	stream_putc(s, 0); + +	stream_putw(s, PREFIX_FAMILY(p)); +	stream_putc(s, p->prefixlen); +	switch (PREFIX_FAMILY(p)) { +	case AF_INET: +		stream_put_in_addr(s, &p->u.prefix4); +		break; +	case AF_INET6: +		stream_put(s, &(p->u.prefix6), 16); +		break; +	default: +		break; +	} +	stream_putw_at(s, 0, stream_get_endp(s)); + +	ret = zclient_send_message(zclient); +	if (ret < 0) +		zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); + + +	if (PIM_DEBUG_TRACE) { +		char buf[PREFIX2STR_BUFFER]; +		prefix2str(p, buf, sizeof(buf)); +		zlog_debug("%s: NHT %sregistered addr %s with Zebra ret:%d ", +			   __PRETTY_FUNCTION__, +			   (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", +			   buf, ret); +	} + +	return;  } -struct pim_nexthop_cache * -pim_nexthop_cache_find (struct pim_rpf *rpf) +struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf)  { -  struct pim_nexthop_cache *pnc = NULL; -  struct pim_nexthop_cache lookup; +	struct pim_nexthop_cache *pnc = NULL; +	struct pim_nexthop_cache lookup; -  lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; -  lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; -  lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; +	lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; +	lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; +	lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; -  pnc = hash_lookup (pimg->rpf_hash, &lookup); - -  return pnc; +	pnc = hash_lookup(pimg->rpf_hash, &lookup); +	return pnc;  } -struct pim_nexthop_cache * -pim_nexthop_cache_add (struct pim_rpf *rpf_addr) +struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr)  { -  struct pim_nexthop_cache *pnc; - -  pnc = XCALLOC (MTYPE_PIM_NEXTHOP_CACHE, sizeof (struct pim_nexthop_cache)); -  if (!pnc) -    { -      zlog_err ("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); -      return NULL; -    } -  pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; -  pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; -  pnc->rpf.rpf_addr.u.prefix4.s_addr = rpf_addr->rpf_addr.u.prefix4.s_addr; - -  pnc = hash_get (pimg->rpf_hash, pnc, hash_alloc_intern); - -  pnc->rp_list = list_new (); -  pnc->rp_list->cmp = pim_rp_list_cmp; - -  pnc->upstream_list = list_new (); -  pnc->upstream_list->cmp = pim_upstream_compare; - -  if (PIM_DEBUG_ZEBRA) -    { -      char rpf_str[PREFIX_STRLEN]; -      pim_addr_dump ("<nht?>", &rpf_addr->rpf_addr, rpf_str, -                     sizeof (rpf_str)); -      zlog_debug ("%s: NHT hash node, RP and UP lists allocated for %s ", -                  __PRETTY_FUNCTION__, rpf_str); -    } - -  return pnc; +	struct pim_nexthop_cache *pnc; + +	pnc = XCALLOC(MTYPE_PIM_NEXTHOP_CACHE, +		      sizeof(struct pim_nexthop_cache)); +	if (!pnc) { +		zlog_err("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); +		return NULL; +	} +	pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; +	pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; +	pnc->rpf.rpf_addr.u.prefix4.s_addr = +		rpf_addr->rpf_addr.u.prefix4.s_addr; + +	pnc = hash_get(pimg->rpf_hash, pnc, hash_alloc_intern); + +	pnc->rp_list = list_new(); +	pnc->rp_list->cmp = pim_rp_list_cmp; + +	pnc->upstream_list = list_new(); +	pnc->upstream_list->cmp = pim_upstream_compare; + +	if (PIM_DEBUG_ZEBRA) { +		char rpf_str[PREFIX_STRLEN]; +		pim_addr_dump("<nht?>", &rpf_addr->rpf_addr, rpf_str, +			      sizeof(rpf_str)); +		zlog_debug( +			"%s: NHT hash node, RP and UP lists allocated for %s ", +			__PRETTY_FUNCTION__, rpf_str); +	} + +	return pnc;  }  /* This API is used to Register an address with Zebra     ret 1 means nexthop cache is found.  */ -int -pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, -                           struct rp_info *rp, -                           struct pim_nexthop_cache *out_pnc) +int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up, +			      struct rp_info *rp, +			      struct pim_nexthop_cache *out_pnc)  { -  struct pim_nexthop_cache *pnc = NULL; -  struct pim_rpf rpf; -  struct listnode *ch_node = NULL; -  struct zclient *zclient = NULL; - -  zclient = pim_zebra_zclient_get (); -  memset (&rpf, 0, sizeof (struct pim_rpf)); -  rpf.rpf_addr.family = addr->family; -  rpf.rpf_addr.prefixlen = addr->prefixlen; -  rpf.rpf_addr.u.prefix4 = addr->u.prefix4; - -  pnc = pim_nexthop_cache_find (&rpf); -  if (!pnc) -    { -      pnc = pim_nexthop_cache_add (&rpf); -      if (pnc) -        pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER); -      else -        { -          char rpf_str[PREFIX_STRLEN]; -          pim_addr_dump ("<nht-pnc?>", addr, rpf_str, sizeof (rpf_str)); -          zlog_warn ("%s: pnc node allocation failed. addr %s ", -                     __PRETTY_FUNCTION__, rpf_str); -          return -1; -        } -    } - -  if (rp != NULL) -    { -      ch_node = listnode_lookup (pnc->rp_list, rp); -      if (ch_node == NULL) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char rp_str[PREFIX_STRLEN]; -              pim_addr_dump ("<rp?>", &rp->rp.rpf_addr, rp_str, -                             sizeof (rp_str)); -              zlog_debug ("%s: Add RP %s node to pnc cached list", -                          __PRETTY_FUNCTION__, rp_str); -            } -          listnode_add_sort (pnc->rp_list, rp); -        } -    } - -  if (up != NULL) -    { -      ch_node = listnode_lookup (pnc->upstream_list, up); -      if (ch_node == NULL) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char buf[PREFIX2STR_BUFFER]; -              prefix2str (addr, buf, sizeof (buf)); -              zlog_debug ("%s: Add upstream %s node to pnc cached list, rpf %s", -                 __PRETTY_FUNCTION__, up->sg_str, buf); -            } -          listnode_add_sort (pnc->upstream_list, up); -        } -    } - -  if (pnc && CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID)) -    { -      memcpy (out_pnc, pnc, sizeof (struct pim_nexthop_cache)); -      return 1; -    } - -  return 0; +	struct pim_nexthop_cache *pnc = NULL; +	struct pim_rpf rpf; +	struct listnode *ch_node = NULL; +	struct zclient *zclient = NULL; + +	zclient = pim_zebra_zclient_get(); +	memset(&rpf, 0, sizeof(struct pim_rpf)); +	rpf.rpf_addr.family = addr->family; +	rpf.rpf_addr.prefixlen = addr->prefixlen; +	rpf.rpf_addr.u.prefix4 = addr->u.prefix4; + +	pnc = pim_nexthop_cache_find(&rpf); +	if (!pnc) { +		pnc = pim_nexthop_cache_add(&rpf); +		if (pnc) +			pim_sendmsg_zebra_rnh(zclient, pnc, +					      ZEBRA_NEXTHOP_REGISTER); +		else { +			char rpf_str[PREFIX_STRLEN]; +			pim_addr_dump("<nht-pnc?>", addr, rpf_str, +				      sizeof(rpf_str)); +			zlog_warn("%s: pnc node allocation failed. addr %s ", +				  __PRETTY_FUNCTION__, rpf_str); +			return -1; +		} +	} + +	if (rp != NULL) { +		ch_node = listnode_lookup(pnc->rp_list, rp); +		if (ch_node == NULL) { +			if (PIM_DEBUG_ZEBRA) { +				char rp_str[PREFIX_STRLEN]; +				pim_addr_dump("<rp?>", &rp->rp.rpf_addr, rp_str, +					      sizeof(rp_str)); +				zlog_debug( +					"%s: Add RP %s node to pnc cached list", +					__PRETTY_FUNCTION__, rp_str); +			} +			listnode_add_sort(pnc->rp_list, rp); +		} +	} + +	if (up != NULL) { +		ch_node = listnode_lookup(pnc->upstream_list, up); +		if (ch_node == NULL) { +			if (PIM_DEBUG_ZEBRA) { +				char buf[PREFIX2STR_BUFFER]; +				prefix2str(addr, buf, sizeof(buf)); +				zlog_debug( +					"%s: Add upstream %s node to pnc cached list, rpf %s", +					__PRETTY_FUNCTION__, up->sg_str, buf); +			} +			listnode_add_sort(pnc->upstream_list, up); +		} +	} + +	if (pnc && CHECK_FLAG(pnc->flags, PIM_NEXTHOP_VALID)) { +		memcpy(out_pnc, pnc, sizeof(struct pim_nexthop_cache)); +		return 1; +	} + +	return 0;  } -void -pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, -                            struct rp_info *rp) +void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up, +				struct rp_info *rp)  { -  struct pim_nexthop_cache *pnc = NULL; -  struct pim_nexthop_cache lookup; -  struct zclient *zclient = NULL; - -  zclient = pim_zebra_zclient_get (); - -  /* Remove from RPF hash if it is the last entry */ -  lookup.rpf.rpf_addr = *addr; -  pnc = hash_lookup (pimg->rpf_hash, &lookup); -  if (pnc) -    { -      if (rp) -        listnode_delete (pnc->rp_list, rp); -      if (up) -        listnode_delete (pnc->upstream_list, up); - -      if (PIM_DEBUG_ZEBRA) -        zlog_debug ("%s: NHT rp_list count:%d upstream_list count:%d ", -                    __PRETTY_FUNCTION__, pnc->rp_list->count, -                    pnc->upstream_list->count); - -      if (pnc->rp_list->count == 0 && pnc->upstream_list->count == 0) -        { -          pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_UNREGISTER); - -          list_delete (pnc->rp_list); -          list_delete (pnc->upstream_list); - -          hash_release (pimg->rpf_hash, pnc); -          if (pnc->nexthop) -            nexthops_free (pnc->nexthop); -          XFREE (MTYPE_PIM_NEXTHOP_CACHE, pnc); -        } -    } +	struct pim_nexthop_cache *pnc = NULL; +	struct pim_nexthop_cache lookup; +	struct zclient *zclient = NULL; + +	zclient = pim_zebra_zclient_get(); + +	/* Remove from RPF hash if it is the last entry */ +	lookup.rpf.rpf_addr = *addr; +	pnc = hash_lookup(pimg->rpf_hash, &lookup); +	if (pnc) { +		if (rp) +			listnode_delete(pnc->rp_list, rp); +		if (up) +			listnode_delete(pnc->upstream_list, up); + +		if (PIM_DEBUG_ZEBRA) +			zlog_debug( +				"%s: NHT rp_list count:%d upstream_list count:%d ", +				__PRETTY_FUNCTION__, pnc->rp_list->count, +				pnc->upstream_list->count); + +		if (pnc->rp_list->count == 0 +		    && pnc->upstream_list->count == 0) { +			pim_sendmsg_zebra_rnh(zclient, pnc, +					      ZEBRA_NEXTHOP_UNREGISTER); + +			list_delete(pnc->rp_list); +			list_delete(pnc->upstream_list); + +			hash_release(pimg->rpf_hash, pnc); +			if (pnc->nexthop) +				nexthops_free(pnc->nexthop); +			XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc); +		} +	}  }  /* Update RP nexthop info based on Nexthop update received from Zebra.*/ -int -pim_update_rp_nh (struct pim_nexthop_cache *pnc) +int pim_update_rp_nh(struct pim_nexthop_cache *pnc)  { -  struct listnode *node = NULL; -  struct rp_info *rp_info = NULL; -  int ret = 0; - -  /*Traverse RP list and update each RP Nexthop info */ -  for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info)) -    { -      if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) -        continue; - -      //Compute PIM RPF using cached nexthop -      ret = pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop, -                           &rp_info->rp.rpf_addr, &rp_info->group, 1); - -      if (PIM_DEBUG_TRACE) -        { -          char rp_str[PREFIX_STRLEN]; -          pim_addr_dump ("<rp?>", &rp_info->rp.rpf_addr, rp_str, -                         sizeof (rp_str)); -          zlog_debug ("%s: NHT update, nexthop for RP %s is interface %s ", -                      __PRETTY_FUNCTION__, rp_str, -                      rp_info->rp.source_nexthop.interface->name); -        } -    } - -  if (ret) -    return 0; - -  return 1; +	struct listnode *node = NULL; +	struct rp_info *rp_info = NULL; +	int ret = 0; + +	/*Traverse RP list and update each RP Nexthop info */ +	for (ALL_LIST_ELEMENTS_RO(pnc->rp_list, node, rp_info)) { +		if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) +			continue; + +		// Compute PIM RPF using cached nexthop +		ret = pim_ecmp_nexthop_search(pnc, &rp_info->rp.source_nexthop, +					      &rp_info->rp.rpf_addr, +					      &rp_info->group, 1); + +		if (PIM_DEBUG_TRACE) { +			char rp_str[PREFIX_STRLEN]; +			pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, rp_str, +				      sizeof(rp_str)); +			zlog_debug( +				"%s: NHT update, nexthop for RP %s is interface %s ", +				__PRETTY_FUNCTION__, rp_str, +				rp_info->rp.source_nexthop.interface->name); +		} +	} + +	if (ret) +		return 0; + +	return 1;  }  /* This API is used to traverse nexthop cache of RPF addr @@ -303,771 +292,779 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)     unresolved state and due to event like pim neighbor     UP event if it can be resolved.  */ -void -pim_resolve_upstream_nh (struct prefix *nht_p) +void pim_resolve_upstream_nh(struct prefix *nht_p)  { -  struct nexthop *nh_node = NULL; -  struct pim_nexthop_cache pnc; -  struct pim_neighbor *nbr = NULL; - -  memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -  if ((pim_find_or_track_nexthop (nht_p, NULL, NULL, &pnc)) == 1) -    { -      for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) -        { -          if (nh_node->gate.ipv4.s_addr == 0) -            { -              struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex, -                                                             VRF_DEFAULT); -              nbr = pim_neighbor_find_if (ifp1); -              if (nbr) -                { -                  nh_node->gate.ipv4 = nbr->source_addr; -                  if (PIM_DEBUG_TRACE) -                    { -                      char str[PREFIX_STRLEN]; -                      char str1[INET_ADDRSTRLEN]; -                      pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str1, -                                      sizeof (str1)); -                      pim_addr_dump ("<nht_addr?>", nht_p, str, sizeof (str)); -                      zlog_debug ("%s: addr %s new nexthop addr %s interface %s", -                              __PRETTY_FUNCTION__, str, str1, ifp1->name); -                    } -                } -            } -        } -    } +	struct nexthop *nh_node = NULL; +	struct pim_nexthop_cache pnc; +	struct pim_neighbor *nbr = NULL; + +	memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +	if ((pim_find_or_track_nexthop(nht_p, NULL, NULL, &pnc)) == 1) { +		for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) { +			if (nh_node->gate.ipv4.s_addr == 0) { +				struct interface *ifp1 = if_lookup_by_index( +					nh_node->ifindex, VRF_DEFAULT); +				nbr = pim_neighbor_find_if(ifp1); +				if (nbr) { +					nh_node->gate.ipv4 = nbr->source_addr; +					if (PIM_DEBUG_TRACE) { +						char str[PREFIX_STRLEN]; +						char str1[INET_ADDRSTRLEN]; +						pim_inet4_dump("<nht_nbr?>", +							       nbr->source_addr, +							       str1, +							       sizeof(str1)); +						pim_addr_dump("<nht_addr?>", +							      nht_p, str, +							      sizeof(str)); +						zlog_debug( +							"%s: addr %s new nexthop addr %s interface %s", +							__PRETTY_FUNCTION__, +							str, str1, ifp1->name); +					} +				} +			} +		} +	}  }  /* Update Upstream nexthop info based on Nexthop update received from Zebra.*/ -static int -pim_update_upstream_nh (struct pim_nexthop_cache *pnc) +static int pim_update_upstream_nh(struct pim_nexthop_cache *pnc)  { -  struct listnode     *up_node; -  struct listnode     *ifnode; -  struct listnode     *up_nextnode; -  struct listnode     *node; -  struct pim_upstream *up = NULL; -  struct interface    *ifp = NULL; -  int                 vif_index = 0; - -  for (ALL_LIST_ELEMENTS (pnc->upstream_list, up_node, up_nextnode, up)) -    { -      enum pim_rpf_result rpf_result; -      struct pim_rpf old; - -      old.source_nexthop.interface = up->rpf.source_nexthop.interface; -      rpf_result = pim_rpf_update (up, &old, 0); -      if (rpf_result == PIM_RPF_FAILURE) -        continue; - -      /* update kernel multicast forwarding cache (MFC) */ -      if (up->channel_oil) -        { -          ifindex_t ifindex = 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 (up->channel_oil, vif_index); -          else -            { -              if (PIM_DEBUG_ZEBRA) -                zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", -                   __PRETTY_FUNCTION__, up->sg_str, -                   up->rpf.source_nexthop.interface->name); -            } -        } - -      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 && 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 && !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 */ - -      if (PIM_DEBUG_TRACE) -        { -          zlog_debug ("%s: NHT upstream %s old ifp %s new ifp %s", -                      __PRETTY_FUNCTION__, up->sg_str, -                      old.source_nexthop.interface->name, -                      up->rpf.source_nexthop.interface->name); -        } -    }                           /* for (pnc->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); -          } -      } - -  return 0; +	struct listnode *up_node; +	struct listnode *ifnode; +	struct listnode *up_nextnode; +	struct listnode *node; +	struct pim_upstream *up = NULL; +	struct interface *ifp = NULL; +	int vif_index = 0; + +	for (ALL_LIST_ELEMENTS(pnc->upstream_list, up_node, up_nextnode, up)) { +		enum pim_rpf_result rpf_result; +		struct pim_rpf old; + +		old.source_nexthop.interface = up->rpf.source_nexthop.interface; +		rpf_result = pim_rpf_update(up, &old, 0); +		if (rpf_result == PIM_RPF_FAILURE) +			continue; + +		/* update kernel multicast forwarding cache (MFC) */ +		if (up->channel_oil) { +			ifindex_t ifindex = +				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(up->channel_oil, +							vif_index); +			else { +				if (PIM_DEBUG_ZEBRA) +					zlog_debug( +						"%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", +						__PRETTY_FUNCTION__, up->sg_str, +						up->rpf.source_nexthop +							.interface->name); +			} +		} + +		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 +			    && 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 +				    && !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 */ + +		if (PIM_DEBUG_TRACE) { +			zlog_debug("%s: NHT upstream %s old ifp %s new ifp %s", +				   __PRETTY_FUNCTION__, up->sg_str, +				   old.source_nexthop.interface->name, +				   up->rpf.source_nexthop.interface->name); +		} +	} /* for (pnc->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); +			} +		} + +	return 0;  } -uint32_t -pim_compute_ecmp_hash (struct prefix * src, struct prefix * grp) +uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp)  { -  uint32_t hash_val; -  uint32_t s = 0, g = 0; - -  if ((!src)) -    return 0; - -  switch (src->family) -    { -    case AF_INET: -      { -        s = src->u.prefix4.s_addr; -        s = s == 0 ? 1 : s; -        if (grp) -          g = grp->u.prefix4.s_addr; -      } -      break; -    default: -      break; -    } - -  hash_val = jhash_2words (g, s, 101); -  if (PIM_DEBUG_PIM_TRACE_DETAIL) -    { -      char buf[PREFIX2STR_BUFFER]; -      char bufg[PREFIX2STR_BUFFER]; -      prefix2str (src, buf, sizeof (buf)); -      if (grp) -        prefix2str (grp, bufg, sizeof (bufg)); -      zlog_debug ("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, buf, -                  grp ? bufg : "", hash_val); - -    } -  return hash_val; +	uint32_t hash_val; +	uint32_t s = 0, g = 0; + +	if ((!src)) +		return 0; + +	switch (src->family) { +	case AF_INET: { +		s = src->u.prefix4.s_addr; +		s = s == 0 ? 1 : s; +		if (grp) +			g = grp->u.prefix4.s_addr; +	} break; +	default: +		break; +	} + +	hash_val = jhash_2words(g, s, 101); +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		char buf[PREFIX2STR_BUFFER]; +		char bufg[PREFIX2STR_BUFFER]; +		prefix2str(src, buf, sizeof(buf)); +		if (grp) +			prefix2str(grp, bufg, sizeof(bufg)); +		zlog_debug("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, +			   buf, grp ? bufg : "", hash_val); +	} +	return hash_val;  } -int -pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc, -                         struct pim_nexthop *nexthop, struct prefix *src, -                         struct prefix *grp, int neighbor_needed) +int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc, +			    struct pim_nexthop *nexthop, struct prefix *src, +			    struct prefix *grp, int neighbor_needed)  { -  struct pim_neighbor *nbr = NULL; -  struct nexthop *nh_node = NULL; -  ifindex_t first_ifindex; -  struct interface *ifp = NULL; -  uint32_t hash_val = 0, mod_val = 0; -  uint8_t nh_iter = 0, found = 0; - -  if (!pnc || !pnc->nexthop_num || !nexthop) -    return -1; - -  //Current Nexthop is VALID, check to stay on the current path. -  if (nexthop->interface && nexthop->interface->info && -      nexthop->mrib_nexthop_addr.u.prefix4.s_addr != -      PIM_NET_INADDR_ANY) -    { -      /* User configured knob to explicitly switch -         to new path is disabled or current path -         metric is less than nexthop update. -       */ - -      if (qpim_ecmp_rebalance_enable == 0) -        { -          uint8_t curr_route_valid = 0; -          //Check if current nexthop is present in new updated Nexthop list. -          //If the current nexthop is not valid, candidate to choose new Nexthop. -          for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) -            curr_route_valid = (nexthop->interface->ifindex == nh_node->ifindex); - -          if (curr_route_valid && -              !pim_if_connected_to_source (nexthop->interface, -                                           src->u.prefix4)) -            { -              nbr = pim_neighbor_find (nexthop->interface, -                                       nexthop->mrib_nexthop_addr.u.prefix4); -              if (!nbr && !if_is_loopback (nexthop->interface)) -                { -                  if (PIM_DEBUG_TRACE) -                    zlog_debug ("%s: current nexthop does not have nbr ", -                                __PRETTY_FUNCTION__); -                } -              else -                { -                  if (PIM_DEBUG_TRACE) -                    { -                      char src_str[INET_ADDRSTRLEN]; -                      pim_inet4_dump ("<addr?>", src->u.prefix4, src_str, -                                      sizeof (src_str)); -                      char grp_str[INET_ADDRSTRLEN]; -                      pim_inet4_dump ("<addr?>", grp->u.prefix4, grp_str, -                                      sizeof (grp_str)); -                      zlog_debug ("%s: (%s, %s) current nexthop %s is valid, skipping new path selection", -                         __PRETTY_FUNCTION__, src_str, grp_str, -                         nexthop->interface->name); -                    } -                  return 0; -                } -            } -        } -    } -  if (qpim_ecmp_enable) -    { -      //PIM ECMP flag is enable then choose ECMP path. -      hash_val = pim_compute_ecmp_hash (src, grp); -      mod_val = hash_val % pnc->nexthop_num; -      if (PIM_DEBUG_PIM_TRACE_DETAIL) -        zlog_debug ("%s: hash_val %u mod_val %u ", -                    __PRETTY_FUNCTION__, hash_val, mod_val); -    } - -  for (nh_node = pnc->nexthop; nh_node && (found == 0); -       nh_node = nh_node->next) -    { -      first_ifindex = nh_node->ifindex; -      ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); -      if (!ifp) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str, -                              sizeof (addr_str)); -              zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)", -                 __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); -            } -          if (nh_iter == mod_val) -            mod_val++;          //Select nexthpath -          nh_iter++; -          continue; -        } -      if (!ifp->info) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str, -                              sizeof (addr_str)); -              zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", -                 __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); -            } -          if (nh_iter == mod_val) -            mod_val++;          //Select nexthpath -          nh_iter++; -          continue; -        } - -      if (neighbor_needed -          && !pim_if_connected_to_source (ifp, src->u.prefix4)) -        { -          nbr = pim_neighbor_find (ifp, nh_node->gate.ipv4); -          if (PIM_DEBUG_PIM_TRACE_DETAIL) -            zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); -          if (!nbr && !if_is_loopback (ifp)) -            { -              if (PIM_DEBUG_ZEBRA) -                zlog_debug ("%s: pim nbr not found on input interface %s", -                            __PRETTY_FUNCTION__, ifp->name); -              if (nh_iter == mod_val) -                mod_val++;      //Select nexthpath -              nh_iter++; -              continue; -            } -        } - -      if (nh_iter == mod_val) -        { -          nexthop->interface                    = ifp; -          nexthop->mrib_nexthop_addr.family     = AF_INET; -          nexthop->mrib_nexthop_addr.prefixlen  = IPV4_MAX_BITLEN; -          nexthop->mrib_nexthop_addr.u.prefix4  = nh_node->gate.ipv4; -          nexthop->mrib_metric_preference       = pnc->distance; -          nexthop->mrib_route_metric            = pnc->metric; -          nexthop->last_lookup                  = src->u.prefix4; -          nexthop->last_lookup_time             = pim_time_monotonic_usec (); -          nexthop->nbr                          = nbr; -          found                                 = 1; -          if (PIM_DEBUG_ZEBRA) -            { -              char buf[INET_ADDRSTRLEN]; -              char buf2[INET_ADDRSTRLEN]; -              char buf3[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<src?>", src->u.prefix4, buf2, sizeof (buf2)); -              pim_inet4_dump ("<grp?>", grp->u.prefix4, buf3, sizeof (buf3)); -              pim_inet4_dump ("<rpf?>", -                              nexthop->mrib_nexthop_addr.u.prefix4, buf, -                              sizeof (buf)); -              zlog_debug ("%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d", -                          __PRETTY_FUNCTION__, buf2, buf3, ifp->name, -                          buf, mod_val, nh_iter, qpim_ecmp_enable); -            } -        } -      nh_iter++; -    } - -  if (found) -    return 0; -  else -    return -1; +	struct pim_neighbor *nbr = NULL; +	struct nexthop *nh_node = NULL; +	ifindex_t first_ifindex; +	struct interface *ifp = NULL; +	uint32_t hash_val = 0, mod_val = 0; +	uint8_t nh_iter = 0, found = 0; + +	if (!pnc || !pnc->nexthop_num || !nexthop) +		return -1; + +	// Current Nexthop is VALID, check to stay on the current path. +	if (nexthop->interface && nexthop->interface->info +	    && nexthop->mrib_nexthop_addr.u.prefix4.s_addr +		       != PIM_NET_INADDR_ANY) { +		/* User configured knob to explicitly switch +		   to new path is disabled or current path +		   metric is less than nexthop update. +		 */ + +		if (qpim_ecmp_rebalance_enable == 0) { +			uint8_t curr_route_valid = 0; +			// Check if current nexthop is present in new updated +			// Nexthop list. +			// If the current nexthop is not valid, candidate to +			// choose new Nexthop. +			for (nh_node = pnc->nexthop; nh_node; +			     nh_node = nh_node->next) +				curr_route_valid = (nexthop->interface->ifindex +						    == nh_node->ifindex); + +			if (curr_route_valid +			    && !pim_if_connected_to_source(nexthop->interface, +							   src->u.prefix4)) { +				nbr = pim_neighbor_find( +					nexthop->interface, +					nexthop->mrib_nexthop_addr.u.prefix4); +				if (!nbr +				    && !if_is_loopback(nexthop->interface)) { +					if (PIM_DEBUG_TRACE) +						zlog_debug( +							"%s: current nexthop does not have nbr ", +							__PRETTY_FUNCTION__); +				} else { +					if (PIM_DEBUG_TRACE) { +						char src_str[INET_ADDRSTRLEN]; +						pim_inet4_dump("<addr?>", +							       src->u.prefix4, +							       src_str, +							       sizeof(src_str)); +						char grp_str[INET_ADDRSTRLEN]; +						pim_inet4_dump("<addr?>", +							       grp->u.prefix4, +							       grp_str, +							       sizeof(grp_str)); +						zlog_debug( +							"%s: (%s, %s) current nexthop %s is valid, skipping new path selection", +							__PRETTY_FUNCTION__, +							src_str, grp_str, +							nexthop->interface->name); +					} +					return 0; +				} +			} +		} +	} +	if (qpim_ecmp_enable) { +		// PIM ECMP flag is enable then choose ECMP path. +		hash_val = pim_compute_ecmp_hash(src, grp); +		mod_val = hash_val % pnc->nexthop_num; +		if (PIM_DEBUG_PIM_TRACE_DETAIL) +			zlog_debug("%s: hash_val %u mod_val %u ", +				   __PRETTY_FUNCTION__, hash_val, mod_val); +	} + +	for (nh_node = pnc->nexthop; nh_node && (found == 0); +	     nh_node = nh_node->next) { +		first_ifindex = nh_node->ifindex; +		ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); +		if (!ifp) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", src->u.prefix4, +					       addr_str, sizeof(addr_str)); +				zlog_debug( +					"%s %s: could not find interface for ifindex %d (address %s)", +					__FILE__, __PRETTY_FUNCTION__, +					first_ifindex, addr_str); +			} +			if (nh_iter == mod_val) +				mod_val++; // Select nexthpath +			nh_iter++; +			continue; +		} +		if (!ifp->info) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", src->u.prefix4, +					       addr_str, sizeof(addr_str)); +				zlog_debug( +					"%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", +					__PRETTY_FUNCTION__, ifp->name, +					first_ifindex, addr_str); +			} +			if (nh_iter == mod_val) +				mod_val++; // Select nexthpath +			nh_iter++; +			continue; +		} + +		if (neighbor_needed +		    && !pim_if_connected_to_source(ifp, src->u.prefix4)) { +			nbr = pim_neighbor_find(ifp, nh_node->gate.ipv4); +			if (PIM_DEBUG_PIM_TRACE_DETAIL) +				zlog_debug("ifp name: %s, pim nbr: %p", +					   ifp->name, nbr); +			if (!nbr && !if_is_loopback(ifp)) { +				if (PIM_DEBUG_ZEBRA) +					zlog_debug( +						"%s: pim nbr not found on input interface %s", +						__PRETTY_FUNCTION__, ifp->name); +				if (nh_iter == mod_val) +					mod_val++; // Select nexthpath +				nh_iter++; +				continue; +			} +		} + +		if (nh_iter == mod_val) { +			nexthop->interface = ifp; +			nexthop->mrib_nexthop_addr.family = AF_INET; +			nexthop->mrib_nexthop_addr.prefixlen = IPV4_MAX_BITLEN; +			nexthop->mrib_nexthop_addr.u.prefix4 = +				nh_node->gate.ipv4; +			nexthop->mrib_metric_preference = pnc->distance; +			nexthop->mrib_route_metric = pnc->metric; +			nexthop->last_lookup = src->u.prefix4; +			nexthop->last_lookup_time = pim_time_monotonic_usec(); +			nexthop->nbr = nbr; +			found = 1; +			if (PIM_DEBUG_ZEBRA) { +				char buf[INET_ADDRSTRLEN]; +				char buf2[INET_ADDRSTRLEN]; +				char buf3[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src->u.prefix4, buf2, +					       sizeof(buf2)); +				pim_inet4_dump("<grp?>", grp->u.prefix4, buf3, +					       sizeof(buf3)); +				pim_inet4_dump( +					"<rpf?>", +					nexthop->mrib_nexthop_addr.u.prefix4, +					buf, sizeof(buf)); +				zlog_debug( +					"%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d", +					__PRETTY_FUNCTION__, buf2, buf3, +					ifp->name, buf, mod_val, nh_iter, +					qpim_ecmp_enable); +			} +		} +		nh_iter++; +	} + +	if (found) +		return 0; +	else +		return -1;  } -/* This API is used to parse Registered address nexthop update coming from Zebra */ -int -pim_parse_nexthop_update (int command, struct zclient *zclient, -                          zebra_size_t length, vrf_id_t vrf_id) +/* This API is used to parse Registered address nexthop update coming from Zebra + */ +int pim_parse_nexthop_update(int command, struct zclient *zclient, +			     zebra_size_t length, vrf_id_t vrf_id)  { -  struct stream *s; -  struct prefix p; -  struct nexthop *nexthop; -  struct nexthop *nhlist_head = NULL; -  struct nexthop *nhlist_tail = NULL; -  uint32_t metric, distance; -  u_char nexthop_num = 0; -  int i; -  struct pim_rpf rpf; -  struct pim_nexthop_cache *pnc = NULL; -  struct pim_neighbor *nbr = NULL; -  struct interface *ifp = NULL; -  struct interface *ifp1 = NULL; -  struct pim_interface *pim_ifp = NULL; -  char str[INET_ADDRSTRLEN]; - -  s = zclient->ibuf; -  memset (&p, 0, sizeof (struct prefix)); -  p.family = stream_getw (s); -  p.prefixlen = stream_getc (s); -  switch (p.family) -    { -    case AF_INET: -      p.u.prefix4.s_addr = stream_get_ipv4 (s); -      break; -    case AF_INET6: -      stream_get (&p.u.prefix6, s, 16); -      break; -    default: -      break; -    } - -  if (command == ZEBRA_NEXTHOP_UPDATE) -    { -      rpf.rpf_addr.family = p.family; -      rpf.rpf_addr.prefixlen = p.prefixlen; -      rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; -      pnc = pim_nexthop_cache_find (&rpf); -      if (!pnc) -        { -          if (PIM_DEBUG_TRACE) -            { -              char buf[PREFIX2STR_BUFFER]; -              prefix2str (&rpf.rpf_addr, buf, sizeof (buf)); -              zlog_debug ("%s: Skipping NHT update, addr %s is not in local cached DB.", -                 __PRETTY_FUNCTION__, buf); -            } -          return 0; -        } -    } -  else -    { -      /* -       * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE -       */ -      return 0; -    } - -  pnc->last_update = pim_time_monotonic_usec (); -  distance = stream_getc (s); -  metric = stream_getl (s); -  nexthop_num = stream_getc (s); - -  if (nexthop_num) -    { -      pnc->nexthop_num = 0;     //Only increment for pim enabled rpf. - -      for (i = 0; i < nexthop_num; i++) -        { -          nexthop = nexthop_new (); -          nexthop->type = stream_getc (s); -          switch (nexthop->type) -            { -            case NEXTHOP_TYPE_IPV4: -              nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); -              nexthop->ifindex = stream_getl (s); -              break; -            case NEXTHOP_TYPE_IFINDEX: -              nexthop->ifindex = stream_getl (s); -              break; -            case NEXTHOP_TYPE_IPV4_IFINDEX: -              nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); -              nexthop->ifindex = stream_getl (s); -              break; -            case NEXTHOP_TYPE_IPV6: -              stream_get (&nexthop->gate.ipv6, s, 16); -              break; -            case NEXTHOP_TYPE_IPV6_IFINDEX: -              stream_get (&nexthop->gate.ipv6, s, 16); -              nexthop->ifindex = stream_getl (s); -              ifp1 = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); -              nbr = pim_neighbor_find_if (ifp1); -              /* Overwrite with Nbr address as NH addr */ -              if (nbr) -                { -                  nexthop->gate.ipv4 = nbr->source_addr; -                  if (PIM_DEBUG_TRACE) -                    { -                      pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str, -                                      sizeof (str)); -                      zlog_debug ("%s: NHT using pim nbr addr %s interface %s as rpf", -                                  __PRETTY_FUNCTION__, str, ifp1->name); -                    } -                } -              else -                { -                  if (PIM_DEBUG_TRACE) -                    { -                      pim_ifp = ifp1->info; -                      zlog_debug ("%s: NHT pim nbr not found on interface %s nbr count:%d ", -                                  __PRETTY_FUNCTION__, ifp1->name, -                                  pim_ifp->pim_neighbor_list->count); -                    } -                  //Mark nexthop address to 0 until PIM Nbr is resolved. -                  nexthop->gate.ipv4.s_addr = PIM_NET_INADDR_ANY; -                } - -              break; -            default: -              /* do nothing */ -              break; -            } - -          if (PIM_DEBUG_TRACE) -            { -              char p_str[PREFIX2STR_BUFFER]; -              prefix2str (&p, p_str, sizeof (p_str)); -              zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ", -                 __PRETTY_FUNCTION__, p_str, i + 1, -                 inet_ntoa (nexthop->gate.ipv4), nexthop->type, distance, -                 metric); -            } - -          ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); -          if (!ifp) -            { -              if (PIM_DEBUG_ZEBRA) -                { -                  char buf[NEXTHOP_STRLEN]; -                  zlog_debug ("%s: could not find interface for ifindex %d (addr %s)", -                     __PRETTY_FUNCTION__, nexthop->ifindex, -                     nexthop2str (nexthop, buf, sizeof (buf))); -                } -              nexthop_free (nexthop); -              continue; -            } - -          if (!ifp->info) -            { -              if (PIM_DEBUG_ZEBRA) -                { -                  char buf[NEXTHOP_STRLEN]; -                  zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", -                     __PRETTY_FUNCTION__, ifp->name, nexthop->ifindex, -                     nexthop2str (nexthop, buf, sizeof (buf))); -                } -              nexthop_free (nexthop); -              continue; -            } - -          if (nhlist_tail) -            { -              nhlist_tail->next = nexthop; -              nhlist_tail = nexthop; -            } -          else -            { -              nhlist_tail = nexthop; -              nhlist_head = nexthop; -            } -          //Only keep track of nexthops which are PIM enabled. -          pnc->nexthop_num++; -        } -      /* Reset existing pnc->nexthop before assigning new list */ -      nexthops_free (pnc->nexthop); -      pnc->nexthop = nhlist_head; -      if (pnc->nexthop_num) -        { -          pnc->flags |= PIM_NEXTHOP_VALID; -          pnc->distance = distance; -          pnc->metric = metric; -        } -    } -  else -    { -      pnc->flags &= ~PIM_NEXTHOP_VALID; -      pnc->nexthop_num = nexthop_num; -      nexthops_free (pnc->nexthop); -      pnc->nexthop = NULL; -    } - -  if (PIM_DEBUG_TRACE) -    { -      char buf[PREFIX2STR_BUFFER]; -      prefix2str (&p, buf, sizeof (buf)); -      zlog_debug ("%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d", -         __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id, -         listcount (pnc->upstream_list), listcount (pnc->rp_list)); -    } - -  pim_rpf_set_refresh_time (); - -  if (listcount (pnc->rp_list)) -    pim_update_rp_nh (pnc); -  if (listcount (pnc->upstream_list)) -    pim_update_upstream_nh (pnc); - -  return 0; +	struct stream *s; +	struct prefix p; +	struct nexthop *nexthop; +	struct nexthop *nhlist_head = NULL; +	struct nexthop *nhlist_tail = NULL; +	uint32_t metric, distance; +	u_char nexthop_num = 0; +	int i; +	struct pim_rpf rpf; +	struct pim_nexthop_cache *pnc = NULL; +	struct pim_neighbor *nbr = NULL; +	struct interface *ifp = NULL; +	struct interface *ifp1 = NULL; +	struct pim_interface *pim_ifp = NULL; +	char str[INET_ADDRSTRLEN]; + +	s = zclient->ibuf; +	memset(&p, 0, sizeof(struct prefix)); +	p.family = stream_getw(s); +	p.prefixlen = stream_getc(s); +	switch (p.family) { +	case AF_INET: +		p.u.prefix4.s_addr = stream_get_ipv4(s); +		break; +	case AF_INET6: +		stream_get(&p.u.prefix6, s, 16); +		break; +	default: +		break; +	} + +	if (command == ZEBRA_NEXTHOP_UPDATE) { +		rpf.rpf_addr.family = p.family; +		rpf.rpf_addr.prefixlen = p.prefixlen; +		rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; +		pnc = pim_nexthop_cache_find(&rpf); +		if (!pnc) { +			if (PIM_DEBUG_TRACE) { +				char buf[PREFIX2STR_BUFFER]; +				prefix2str(&rpf.rpf_addr, buf, sizeof(buf)); +				zlog_debug( +					"%s: Skipping NHT update, addr %s is not in local cached DB.", +					__PRETTY_FUNCTION__, buf); +			} +			return 0; +		} +	} else { +		/* +		 * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE +		 */ +		return 0; +	} + +	pnc->last_update = pim_time_monotonic_usec(); +	distance = stream_getc(s); +	metric = stream_getl(s); +	nexthop_num = stream_getc(s); + +	if (nexthop_num) { +		pnc->nexthop_num = 0; // Only increment for pim enabled rpf. + +		for (i = 0; i < nexthop_num; i++) { +			nexthop = nexthop_new(); +			nexthop->type = stream_getc(s); +			switch (nexthop->type) { +			case NEXTHOP_TYPE_IPV4: +				nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); +				nexthop->ifindex = stream_getl(s); +				break; +			case NEXTHOP_TYPE_IFINDEX: +				nexthop->ifindex = stream_getl(s); +				break; +			case NEXTHOP_TYPE_IPV4_IFINDEX: +				nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); +				nexthop->ifindex = stream_getl(s); +				break; +			case NEXTHOP_TYPE_IPV6: +				stream_get(&nexthop->gate.ipv6, s, 16); +				break; +			case NEXTHOP_TYPE_IPV6_IFINDEX: +				stream_get(&nexthop->gate.ipv6, s, 16); +				nexthop->ifindex = stream_getl(s); +				ifp1 = if_lookup_by_index(nexthop->ifindex, +							  VRF_DEFAULT); +				nbr = pim_neighbor_find_if(ifp1); +				/* Overwrite with Nbr address as NH addr */ +				if (nbr) { +					nexthop->gate.ipv4 = nbr->source_addr; +					if (PIM_DEBUG_TRACE) { +						pim_inet4_dump("<nht_nbr?>", +							       nbr->source_addr, +							       str, +							       sizeof(str)); +						zlog_debug( +							"%s: NHT using pim nbr addr %s interface %s as rpf", +							__PRETTY_FUNCTION__, +							str, ifp1->name); +					} +				} else { +					if (PIM_DEBUG_TRACE) { +						pim_ifp = ifp1->info; +						zlog_debug( +							"%s: NHT pim nbr not found on interface %s nbr count:%d ", +							__PRETTY_FUNCTION__, +							ifp1->name, +							pim_ifp->pim_neighbor_list +								->count); +					} +					// Mark nexthop address to 0 until PIM +					// Nbr is resolved. +					nexthop->gate.ipv4.s_addr = +						PIM_NET_INADDR_ANY; +				} + +				break; +			default: +				/* do nothing */ +				break; +			} + +			if (PIM_DEBUG_TRACE) { +				char p_str[PREFIX2STR_BUFFER]; +				prefix2str(&p, p_str, sizeof(p_str)); +				zlog_debug( +					"%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ", +					__PRETTY_FUNCTION__, p_str, i + 1, +					inet_ntoa(nexthop->gate.ipv4), +					nexthop->type, distance, metric); +			} + +			ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); +			if (!ifp) { +				if (PIM_DEBUG_ZEBRA) { +					char buf[NEXTHOP_STRLEN]; +					zlog_debug( +						"%s: could not find interface for ifindex %d (addr %s)", +						__PRETTY_FUNCTION__, +						nexthop->ifindex, +						nexthop2str(nexthop, buf, +							    sizeof(buf))); +				} +				nexthop_free(nexthop); +				continue; +			} + +			if (!ifp->info) { +				if (PIM_DEBUG_ZEBRA) { +					char buf[NEXTHOP_STRLEN]; +					zlog_debug( +						"%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", +						__PRETTY_FUNCTION__, ifp->name, +						nexthop->ifindex, +						nexthop2str(nexthop, buf, +							    sizeof(buf))); +				} +				nexthop_free(nexthop); +				continue; +			} + +			if (nhlist_tail) { +				nhlist_tail->next = nexthop; +				nhlist_tail = nexthop; +			} else { +				nhlist_tail = nexthop; +				nhlist_head = nexthop; +			} +			// Only keep track of nexthops which are PIM enabled. +			pnc->nexthop_num++; +		} +		/* Reset existing pnc->nexthop before assigning new list */ +		nexthops_free(pnc->nexthop); +		pnc->nexthop = nhlist_head; +		if (pnc->nexthop_num) { +			pnc->flags |= PIM_NEXTHOP_VALID; +			pnc->distance = distance; +			pnc->metric = metric; +		} +	} else { +		pnc->flags &= ~PIM_NEXTHOP_VALID; +		pnc->nexthop_num = nexthop_num; +		nexthops_free(pnc->nexthop); +		pnc->nexthop = NULL; +	} + +	if (PIM_DEBUG_TRACE) { +		char buf[PREFIX2STR_BUFFER]; +		prefix2str(&p, buf, sizeof(buf)); +		zlog_debug( +			"%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d", +			__PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, +			vrf_id, listcount(pnc->upstream_list), +			listcount(pnc->rp_list)); +	} + +	pim_rpf_set_refresh_time(); + +	if (listcount(pnc->rp_list)) +		pim_update_rp_nh(pnc); +	if (listcount(pnc->upstream_list)) +		pim_update_upstream_nh(pnc); + +	return 0;  } -int -pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, -                         struct prefix *src, struct prefix *grp, -                         int neighbor_needed) +int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, +			    struct prefix *src, struct prefix *grp, +			    int neighbor_needed)  { -  struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; -  struct pim_neighbor *nbr = NULL; -  int num_ifindex; -  struct interface *ifp; -  int first_ifindex; -  int found = 0; -  uint8_t i = 0; -  uint32_t hash_val = 0, mod_val = 0; - -  if (PIM_DEBUG_TRACE) -    { -      char addr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -      zlog_debug ("%s: Looking up: %s, last lookup time: %lld", -                  __PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time); -    } - -  memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); -  num_ifindex = zclient_lookup_nexthop (nexthop_tab, MULTIPATH_NUM, addr, -                            PIM_NEXTHOP_LOOKUP_MAX); -  if (num_ifindex < 1) -    { -      char addr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -      zlog_warn ("%s %s: could not find nexthop ifindex for address %s", -                 __FILE__, __PRETTY_FUNCTION__, addr_str); -      return -1; -    } - -  //If PIM ECMP enable then choose ECMP path. -  if (qpim_ecmp_enable) -    { -      hash_val = pim_compute_ecmp_hash (src, grp); -      mod_val = hash_val % num_ifindex; -      if (PIM_DEBUG_PIM_TRACE_DETAIL) -        zlog_debug ("%s: hash_val %u mod_val %u", -                    __PRETTY_FUNCTION__, hash_val, mod_val); -    } - -  while (!found && (i < num_ifindex)) -    { -      first_ifindex = nexthop_tab[i].ifindex; - -      ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); -      if (!ifp) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -              zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)", -                 __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); -            } -          if (i == mod_val) -            mod_val++; -          i++; -          continue; -        } - -      if (!ifp->info) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -              zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", -                 __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); -            } -          if (i == mod_val) -            mod_val++; -          i++; -          continue; -        } -      if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) -        { -          nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); -          if (PIM_DEBUG_PIM_TRACE_DETAIL) -            zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); -          if (!nbr && !if_is_loopback (ifp)) -            { -              if (i == mod_val) -                mod_val++; -              i++; -              if (PIM_DEBUG_ZEBRA) -                { -                  char addr_str[INET_ADDRSTRLEN]; -                  pim_inet4_dump ("<addr?>", addr, addr_str, -                                  sizeof (addr_str)); -                  zlog_debug ("%s: NBR not found on input interface %s (RPF for source %s)", -                     __PRETTY_FUNCTION__, ifp->name, addr_str); -                } -              continue; -            } -        } - -      if (i == mod_val) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char nexthop_str[PREFIX_STRLEN]; -              char addr_str[INET_ADDRSTRLEN]; -              pim_addr_dump ("<nexthop?>", &nexthop_tab[i].nexthop_addr, -                             nexthop_str, sizeof (nexthop_str)); -              pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -              zlog_debug ("%s %s: found nhop %s for addr %s interface %s metric %d dist %d", -                 __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str, -                 ifp->name, nexthop_tab[i].route_metric, -                 nexthop_tab[i].protocol_distance); -            } -          /* update nextop data */ -          nexthop->interface                = ifp; -          nexthop->mrib_nexthop_addr        = nexthop_tab[i].nexthop_addr; -          nexthop->mrib_metric_preference   = nexthop_tab[i].protocol_distance; -          nexthop->mrib_route_metric        = nexthop_tab[i].route_metric; -          nexthop->last_lookup              = addr; -          nexthop->last_lookup_time         = pim_time_monotonic_usec(); -          nexthop->nbr                      = nbr; -          found                             = 1; -        } -      i++; -    } -  if (found) -    return 0; -  else -    return -1; +	struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; +	struct pim_neighbor *nbr = NULL; +	int num_ifindex; +	struct interface *ifp; +	int first_ifindex; +	int found = 0; +	uint8_t i = 0; +	uint32_t hash_val = 0, mod_val = 0; + +	if (PIM_DEBUG_TRACE) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_debug("%s: Looking up: %s, last lookup time: %lld", +			   __PRETTY_FUNCTION__, addr_str, +			   nexthop->last_lookup_time); +	} + +	memset(nexthop_tab, 0, +	       sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); +	num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, +					     PIM_NEXTHOP_LOOKUP_MAX); +	if (num_ifindex < 1) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_warn( +			"%s %s: could not find nexthop ifindex for address %s", +			__FILE__, __PRETTY_FUNCTION__, addr_str); +		return -1; +	} + +	// If PIM ECMP enable then choose ECMP path. +	if (qpim_ecmp_enable) { +		hash_val = pim_compute_ecmp_hash(src, grp); +		mod_val = hash_val % num_ifindex; +		if (PIM_DEBUG_PIM_TRACE_DETAIL) +			zlog_debug("%s: hash_val %u mod_val %u", +				   __PRETTY_FUNCTION__, hash_val, mod_val); +	} + +	while (!found && (i < num_ifindex)) { +		first_ifindex = nexthop_tab[i].ifindex; + +		ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); +		if (!ifp) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s %s: could not find interface for ifindex %d (address %s)", +					__FILE__, __PRETTY_FUNCTION__, +					first_ifindex, addr_str); +			} +			if (i == mod_val) +				mod_val++; +			i++; +			continue; +		} + +		if (!ifp->info) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", +					__PRETTY_FUNCTION__, ifp->name, +					first_ifindex, addr_str); +			} +			if (i == mod_val) +				mod_val++; +			i++; +			continue; +		} +		if (neighbor_needed && !pim_if_connected_to_source(ifp, addr)) { +			nbr = pim_neighbor_find( +				ifp, nexthop_tab[i].nexthop_addr.u.prefix4); +			if (PIM_DEBUG_PIM_TRACE_DETAIL) +				zlog_debug("ifp name: %s, pim nbr: %p", +					   ifp->name, nbr); +			if (!nbr && !if_is_loopback(ifp)) { +				if (i == mod_val) +					mod_val++; +				i++; +				if (PIM_DEBUG_ZEBRA) { +					char addr_str[INET_ADDRSTRLEN]; +					pim_inet4_dump("<addr?>", addr, +						       addr_str, +						       sizeof(addr_str)); +					zlog_debug( +						"%s: NBR not found on input interface %s (RPF for source %s)", +						__PRETTY_FUNCTION__, ifp->name, +						addr_str); +				} +				continue; +			} +		} + +		if (i == mod_val) { +			if (PIM_DEBUG_ZEBRA) { +				char nexthop_str[PREFIX_STRLEN]; +				char addr_str[INET_ADDRSTRLEN]; +				pim_addr_dump("<nexthop?>", +					      &nexthop_tab[i].nexthop_addr, +					      nexthop_str, sizeof(nexthop_str)); +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s %s: found nhop %s for addr %s interface %s metric %d dist %d", +					__FILE__, __PRETTY_FUNCTION__, +					nexthop_str, addr_str, ifp->name, +					nexthop_tab[i].route_metric, +					nexthop_tab[i].protocol_distance); +			} +			/* update nextop data */ +			nexthop->interface = ifp; +			nexthop->mrib_nexthop_addr = +				nexthop_tab[i].nexthop_addr; +			nexthop->mrib_metric_preference = +				nexthop_tab[i].protocol_distance; +			nexthop->mrib_route_metric = +				nexthop_tab[i].route_metric; +			nexthop->last_lookup = addr; +			nexthop->last_lookup_time = pim_time_monotonic_usec(); +			nexthop->nbr = nbr; +			found = 1; +		} +		i++; +	} +	if (found) +		return 0; +	else +		return -1;  } -int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, -                                     struct prefix *src, struct prefix *grp) +int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src, +				     struct prefix *grp)  { -  struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; -  int num_ifindex; -  int vif_index; -  ifindex_t first_ifindex; -  uint32_t hash_val = 0, mod_val = 0; - -  memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); -  num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, -                                                PIM_NEXTHOP_LOOKUP_MAX); -  if (num_ifindex < 1) -    { -      if (PIM_DEBUG_ZEBRA) -        { -          char addr_str[INET_ADDRSTRLEN]; -          pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -          zlog_debug("%s %s: could not find nexthop ifindex for address %s", -                __FILE__, __PRETTY_FUNCTION__, -                addr_str); -        } -      return -1; -    } - -  //If PIM ECMP enable then choose ECMP path. -  if (qpim_ecmp_enable) -    { -      hash_val = pim_compute_ecmp_hash (src, grp); -      mod_val = hash_val % num_ifindex; -      if (PIM_DEBUG_PIM_TRACE_DETAIL) -        zlog_debug ("%s: hash_val %u mod_val %u", -                    __PRETTY_FUNCTION__, hash_val, mod_val); -    } - -  first_ifindex = nexthop_tab[mod_val].ifindex; - -  if (PIM_DEBUG_ZEBRA) -    { -      char addr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str)); -      zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s", -                __FILE__, __PRETTY_FUNCTION__, -                first_ifindex, ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); -    } - -  vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); - -  if (vif_index < 0) -    { -      if (PIM_DEBUG_ZEBRA) -        { -          char addr_str[INET_ADDRSTRLEN]; -          pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -          zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s", -                  __FILE__, __PRETTY_FUNCTION__, -                     vif_index, addr_str); -        } -      return -2; -    } - -  return vif_index; +	struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; +	int num_ifindex; +	int vif_index; +	ifindex_t first_ifindex; +	uint32_t hash_val = 0, mod_val = 0; + +	memset(nexthop_tab, 0, +	       sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); +	num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, +					     PIM_NEXTHOP_LOOKUP_MAX); +	if (num_ifindex < 1) { +		if (PIM_DEBUG_ZEBRA) { +			char addr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			zlog_debug( +				"%s %s: could not find nexthop ifindex for address %s", +				__FILE__, __PRETTY_FUNCTION__, addr_str); +		} +		return -1; +	} + +	// If PIM ECMP enable then choose ECMP path. +	if (qpim_ecmp_enable) { +		hash_val = pim_compute_ecmp_hash(src, grp); +		mod_val = hash_val % num_ifindex; +		if (PIM_DEBUG_PIM_TRACE_DETAIL) +			zlog_debug("%s: hash_val %u mod_val %u", +				   __PRETTY_FUNCTION__, hash_val, mod_val); +	} + +	first_ifindex = nexthop_tab[mod_val].ifindex; + +	if (PIM_DEBUG_ZEBRA) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str)); +		zlog_debug( +			"%s %s: found nexthop ifindex=%d (interface %s) for address %s", +			__FILE__, __PRETTY_FUNCTION__, first_ifindex, +			ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); +	} + +	vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); + +	if (vif_index < 0) { +		if (PIM_DEBUG_ZEBRA) { +			char addr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			zlog_debug( +				"%s %s: low vif_index=%d < 1 nexthop for address %s", +				__FILE__, __PRETTY_FUNCTION__, vif_index, +				addr_str); +		} +		return -2; +	} + +	return vif_index;  }  | 
