pimd: fix channel_oil and upstream RPF in sync

During PIM Neighbor change/UP event, pim_scan_oil api
scans all channel oil to see any rpf impacted. Instead of
passing current upstream's RPF it passes current RPF as 0 and
does query to rib for nexhtop (without ECMP/Rebalance). This creates
inconsist RPF between Upstream and Channel oil.
In Channel Oil keep backward pointer to upstream DB and fetch up's
RPF and passed to channel_oil scan.
Decrement channel_oil ref_count in upstream_del when decrementing
up ref_count and it is not the last.
Created ECMP based FIB lookup API.

Testing Done:
Performed following testing on tester setup:
5 x LHR, 4 x MSDP Spines, 6 Sources each sending to 1023 groups from one of the spines.
Total send rate 8Mpps.
Test that caused problems was to reboot every device at the same time.
After fix performed 5 iterations of reboot devices and show no sign of the problem.

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
This commit is contained in:
Chirag Shah 2017-04-27 11:01:32 -07:00
parent 8b3366bae4
commit 815c33c92f
8 changed files with 245 additions and 228 deletions

View file

@ -357,10 +357,11 @@ void igmp_source_delete(struct igmp_source *source)
char source_str[INET_ADDRSTRLEN]; char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s", zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d",
source_str, group_str, source_str, group_str,
group->group_igmp_sock->fd, group->group_igmp_sock->fd,
group->group_igmp_sock->interface->name); group->group_igmp_sock->interface->name,
source->source_channel_oil ? source->source_channel_oil->oil_ref_count : 0);
} }
source_timer_off(group, source); source_timer_off(group, source);

View file

@ -147,7 +147,9 @@ pim_nexthop_cache_add (struct pim_rpf *rpf_addr)
return pnc; return pnc;
} }
/* This API is used to Register an address with Zebra */ /* This API is used to Register an address with Zebra
ret 1 means nexthop cache is found.
*/
int int
pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
struct rp_info *rp, struct rp_info *rp,
@ -167,13 +169,6 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
pnc = pim_nexthop_cache_find (&rpf); pnc = pim_nexthop_cache_find (&rpf);
if (!pnc) if (!pnc)
{ {
if (PIM_DEBUG_ZEBRA)
{
char buf[PREFIX2STR_BUFFER];
prefix2str (&rpf.rpf_addr, buf, sizeof (buf));
zlog_debug ("%s: NHT New PNC allocated for addr %s ",
__PRETTY_FUNCTION__, buf);
}
pnc = pim_nexthop_cache_add (&rpf); pnc = pim_nexthop_cache_add (&rpf);
if (pnc) if (pnc)
pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER); pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER);
@ -213,8 +208,7 @@ pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up,
{ {
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str (addr, buf, sizeof (buf)); prefix2str (addr, buf, sizeof (buf));
zlog_debug zlog_debug ("%s: Add upstream %s node to pnc cached list, rpf %s",
("%s: Add upstream %s node to pnc cached list, rpf %s",
__PRETTY_FUNCTION__, up->sg_str, buf); __PRETTY_FUNCTION__, up->sg_str, buf);
} }
listnode_add_sort (pnc->upstream_list, up); listnode_add_sort (pnc->upstream_list, up);
@ -271,11 +265,12 @@ pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up,
} }
/* Update RP nexthop info based on Nexthop update received from Zebra.*/ /* Update RP nexthop info based on Nexthop update received from Zebra.*/
static int int
pim_update_rp_nh (struct pim_nexthop_cache *pnc) pim_update_rp_nh (struct pim_nexthop_cache *pnc)
{ {
struct listnode *node = NULL; struct listnode *node = NULL;
struct rp_info *rp_info = NULL; struct rp_info *rp_info = NULL;
int ret = 0;
/*Traverse RP list and update each RP Nexthop info */ /*Traverse RP list and update each RP Nexthop info */
for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info)) for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info))
@ -284,8 +279,8 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)
continue; continue;
//Compute PIM RPF using cached nexthop //Compute PIM RPF using cached nexthop
pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop, ret = pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop,
&rp_info->rp.rpf_addr, &rp_info->group, 1); &rp_info->rp.rpf_addr, &rp_info->group, 1);
if (PIM_DEBUG_TRACE) if (PIM_DEBUG_TRACE)
{ {
@ -298,7 +293,10 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)
} }
} }
return 0; if (ret)
return 0;
return 1;
} }
/* This API is used to traverse nexthop cache of RPF addr /* This API is used to traverse nexthop cache of RPF addr
@ -320,9 +318,9 @@ pim_resolve_upstream_nh (struct prefix *nht_p)
{ {
if (nh_node->gate.ipv4.s_addr == 0) if (nh_node->gate.ipv4.s_addr == 0)
{ {
nbr = struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex,
pim_neighbor_find_if (if_lookup_by_index VRF_DEFAULT);
(nh_node->ifindex, VRF_DEFAULT)); nbr = pim_neighbor_find_if (ifp1);
if (nbr) if (nbr)
{ {
nh_node->gate.ipv4 = nbr->source_addr; nh_node->gate.ipv4 = nbr->source_addr;
@ -333,9 +331,8 @@ pim_resolve_upstream_nh (struct prefix *nht_p)
pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str1, pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str1,
sizeof (str1)); sizeof (str1));
pim_addr_dump ("<nht_addr?>", nht_p, str, sizeof (str)); pim_addr_dump ("<nht_addr?>", nht_p, str, sizeof (str));
zlog_debug zlog_debug ("%s: addr %s new nexthop addr %s interface %s",
("%s: addr %s new nexthop addr %s ifindex %d ", __PRETTY_FUNCTION__, str, str1, ifp1->name);
__PRETTY_FUNCTION__, str, str1, nh_node->ifindex);
} }
} }
} }
@ -368,18 +365,15 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc)
/* update kernel multicast forwarding cache (MFC) */ /* update kernel multicast forwarding cache (MFC) */
if (up->channel_oil) if (up->channel_oil)
{ {
vif_index = ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex;
pim_if_find_vifindex_by_ifindex (up->rpf. vif_index = pim_if_find_vifindex_by_ifindex (ifindex);
source_nexthop.interface->
ifindex);
/* Pass Current selected NH vif index to mroute download */ /* Pass Current selected NH vif index to mroute download */
if (vif_index) if (vif_index)
pim_scan_individual_oil (up->channel_oil, vif_index); pim_scan_individual_oil (up->channel_oil, vif_index);
else else
{ {
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
zlog_debug zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
__PRETTY_FUNCTION__, up->sg_str, __PRETTY_FUNCTION__, up->sg_str,
up->rpf.source_nexthop.interface->name); up->rpf.source_nexthop.interface->name);
} }
@ -490,7 +484,7 @@ pim_compute_ecmp_hash (struct prefix * src, struct prefix * grp)
} }
hash_val = jhash_2words (g, s, 101); hash_val = jhash_2words (g, s, 101);
if (PIM_DEBUG_TRACE) if (PIM_DEBUG_PIM_TRACE_DETAIL)
{ {
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
char bufg[PREFIX2STR_BUFFER]; char bufg[PREFIX2STR_BUFFER];
@ -519,49 +513,57 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
if (!pnc || !pnc->nexthop_num || !nexthop) if (!pnc || !pnc->nexthop_num || !nexthop)
return -1; return -1;
if (qpim_ecmp_enable) //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. /* 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) if (qpim_ecmp_rebalance_enable == 0)
{ {
//Current Nexthop is VALID then stay on the current path. uint8_t curr_route_valid = 0;
if (nexthop->interface && nexthop->interface->info && //Check if current nexthop is present in new updated Nexthop list.
nexthop->mrib_nexthop_addr.u.prefix4.s_addr != //If the current nexthop is not valid, candidate to choose new Nexthop.
PIM_NET_INADDR_ANY) 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))
{ {
if (neighbor_needed nbr = pim_neighbor_find (nexthop->interface,
&& !pim_if_connected_to_source (nexthop->interface, nexthop->mrib_nexthop_addr.u.prefix4);
src->u.prefix4)) if (!nbr && !if_is_loopback (nexthop->interface))
{ {
nbr = pim_neighbor_find (nexthop->interface, if (PIM_DEBUG_TRACE)
nexthop->mrib_nexthop_addr. zlog_debug ("%s: current nexthop does not have nbr ",
u.prefix4); __PRETTY_FUNCTION__);
if (!nbr && !if_is_loopback (nexthop->interface)) }
else
{
if (PIM_DEBUG_TRACE)
{ {
if (PIM_DEBUG_TRACE) char src_str[INET_ADDRSTRLEN];
zlog_debug ("%s: current nexthop does not have nbr ", pim_inet4_dump ("<addr?>", src->u.prefix4, src_str,
__PRETTY_FUNCTION__); sizeof (src_str));
} char grp_str[INET_ADDRSTRLEN];
else pim_inet4_dump ("<addr?>", grp->u.prefix4, grp_str,
{ sizeof (grp_str));
if (PIM_DEBUG_TRACE) zlog_debug ("%s: (%s, %s) current nexthop %s is valid, skipping new path selection",
{ __PRETTY_FUNCTION__, src_str, grp_str,
char src_str[INET_ADDRSTRLEN]; nexthop->interface->name);
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 %d is valid, not choosing new path",
__PRETTY_FUNCTION__, src_str, grp_str,
nexthop->interface->ifindex);
}
return 0;
} }
return 0;
} }
} }
} }
}
if (qpim_ecmp_enable)
{
//PIM ECMP flag is enable then choose ECMP path. //PIM ECMP flag is enable then choose ECMP path.
hash_val = pim_compute_ecmp_hash (src, grp); hash_val = pim_compute_ecmp_hash (src, grp);
mod_val = hash_val % pnc->nexthop_num; mod_val = hash_val % pnc->nexthop_num;
@ -574,7 +576,7 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
nh_node = nh_node->next) nh_node = nh_node->next)
{ {
first_ifindex = nh_node->ifindex; first_ifindex = nh_node->ifindex;
ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT);
if (!ifp) if (!ifp)
{ {
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
@ -582,8 +584,7 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
char addr_str[INET_ADDRSTRLEN]; char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str, pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str,
sizeof (addr_str)); sizeof (addr_str));
zlog_debug zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)",
("%s %s: could not find interface for ifindex %d (address %s)",
__FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str);
} }
if (nh_iter == mod_val) if (nh_iter == mod_val)
@ -598,8 +599,7 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
char addr_str[INET_ADDRSTRLEN]; char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str, pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str,
sizeof (addr_str)); sizeof (addr_str));
zlog_debug zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str);
} }
if (nh_iter == mod_val) if (nh_iter == mod_val)
@ -617,9 +617,8 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
if (!nbr && !if_is_loopback (ifp)) if (!nbr && !if_is_loopback (ifp))
{ {
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
zlog_debug zlog_debug ("%s: pim nbr not found on input interface %s",
("%s: pim nbr not found on input interface %s", __PRETTY_FUNCTION__, ifp->name);
__PRETTY_FUNCTION__, ifp->name);
if (nh_iter == mod_val) if (nh_iter == mod_val)
mod_val++; //Select nexthpath mod_val++; //Select nexthpath
nh_iter++; nh_iter++;
@ -639,30 +638,22 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
nexthop->last_lookup_time = pim_time_monotonic_usec (); nexthop->last_lookup_time = pim_time_monotonic_usec ();
nexthop->nbr = nbr; nexthop->nbr = nbr;
found = 1; found = 1;
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
{ {
char buf[NEXTHOP_STRLEN]; char buf[INET_ADDRSTRLEN];
char buf2[PREFIX2STR_BUFFER]; char buf2[INET_ADDRSTRLEN];
char buf3[PREFIX2STR_BUFFER]; char buf3[INET_ADDRSTRLEN];
char buf4[PREFIX2STR_BUFFER];
pim_inet4_dump ("<src?>", src->u.prefix4, buf2, sizeof (buf2)); pim_inet4_dump ("<src?>", src->u.prefix4, buf2, sizeof (buf2));
if (grp) pim_inet4_dump ("<grp?>", grp->u.prefix4, buf3, sizeof (buf3));
pim_inet4_dump ("<src?>", grp->u.prefix4, buf3,
sizeof (buf3));
pim_inet4_dump ("<rpf?>", pim_inet4_dump ("<rpf?>",
nexthop->mrib_nexthop_addr.u.prefix4, buf4, nexthop->mrib_nexthop_addr.u.prefix4, buf,
sizeof (buf4)); sizeof (buf));
snprintf (buf, sizeof (buf), "%s if %u", zlog_debug ("%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d",
inet_ntoa (nh_node->gate.ipv4), nh_node->ifindex); __PRETTY_FUNCTION__, buf2, buf3, ifp->name,
zlog_debug buf, mod_val, nh_iter, qpim_ecmp_enable);
("%s: NHT %s %s selected nhop interface %s nhop %s (%s) mod_val:%u iter:%d ecmp_enable:%d",
__PRETTY_FUNCTION__, buf2, grp ? buf3 : " ", ifp->name,
buf, buf4, mod_val, nh_iter, qpim_ecmp_enable);
} }
} }
nh_iter++; nh_iter++;
} }
if (found) if (found)
@ -717,8 +708,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
{ {
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str (&rpf.rpf_addr, buf, sizeof (buf)); prefix2str (&rpf.rpf_addr, buf, sizeof (buf));
zlog_debug zlog_debug ("%s: Skipping NHT update, addr %s is not in local cached DB.",
("%s: Skipping NHT update, addr %s is not in local cached DB.",
__PRETTY_FUNCTION__, buf); __PRETTY_FUNCTION__, buf);
} }
return 0; return 0;
@ -737,16 +727,6 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
metric = stream_getl (s); metric = stream_getl (s);
nexthop_num = stream_getc (s); nexthop_num = stream_getc (s);
if (PIM_DEBUG_TRACE)
{
char buf[PREFIX2STR_BUFFER];
prefix2str (&p, buf, sizeof (buf));
zlog_debug
("%s: NHT Update for %s nexthop_num %d vrf:%d upcount %d rpcount %d",
__PRETTY_FUNCTION__, buf, nexthop_num, vrf_id,
listcount (pnc->upstream_list), listcount (pnc->rp_list));
}
if (nexthop_num) if (nexthop_num)
{ {
pnc->nexthop_num = 0; //Only increment for pim enabled rpf. pnc->nexthop_num = 0; //Only increment for pim enabled rpf.
@ -774,9 +754,8 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6_IFINDEX:
stream_get (&nexthop->gate.ipv6, s, 16); stream_get (&nexthop->gate.ipv6, s, 16);
nexthop->ifindex = stream_getl (s); nexthop->ifindex = stream_getl (s);
nbr = struct interface *ifp1 = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT);
pim_neighbor_find_if (if_lookup_by_index nbr = pim_neighbor_find_if (ifp1);
(nexthop->ifindex, VRF_DEFAULT));
/* Overwrite with Nbr address as NH addr */ /* Overwrite with Nbr address as NH addr */
if (nbr) if (nbr)
{ {
@ -786,21 +765,16 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
char str[INET_ADDRSTRLEN]; char str[INET_ADDRSTRLEN];
pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str, pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str,
sizeof (str)); sizeof (str));
zlog_debug zlog_debug ("%s: NHT using pim nbr addr %s interface %s as rpf",
("%s: NHT using pim nbr addr %s ifindex %d as rpf", __PRETTY_FUNCTION__, str, ifp1->name);
__PRETTY_FUNCTION__, str, nexthop->ifindex);
} }
} }
else else
{ {
if (PIM_DEBUG_TRACE) if (PIM_DEBUG_TRACE)
{ {
struct interface *ifp1 =
if_lookup_by_index (nexthop->ifindex,
VRF_DEFAULT);
struct pim_interface *pim_ifp = ifp1->info; struct pim_interface *pim_ifp = ifp1->info;
zlog_debug zlog_debug ("%s: NHT pim nbr not found on interface %s nbr count:%d ",
("%s: NHT pim nbr not found on interface %s nbr count:%d ",
__PRETTY_FUNCTION__, ifp1->name, __PRETTY_FUNCTION__, ifp1->name,
pim_ifp->pim_neighbor_list->count); pim_ifp->pim_neighbor_list->count);
} }
@ -818,9 +792,10 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
{ {
char p_str[PREFIX2STR_BUFFER]; char p_str[PREFIX2STR_BUFFER];
prefix2str (&p, p_str, sizeof (p_str)); prefix2str (&p, p_str, sizeof (p_str));
zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d", zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ",
__PRETTY_FUNCTION__, p_str, i + 1, __PRETTY_FUNCTION__, p_str, i + 1,
inet_ntoa (nexthop->gate.ipv4), nexthop->type); inet_ntoa (nexthop->gate.ipv4), nexthop->type, distance,
metric);
} }
ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT);
@ -829,8 +804,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
{ {
char buf[NEXTHOP_STRLEN]; char buf[NEXTHOP_STRLEN];
zlog_debug zlog_debug ("%s: could not find interface for ifindex %d (addr %s)",
("%s: could not find interface for ifindex %d (addr %s)",
__PRETTY_FUNCTION__, nexthop->ifindex, __PRETTY_FUNCTION__, nexthop->ifindex,
nexthop2str (nexthop, buf, sizeof (buf))); nexthop2str (nexthop, buf, sizeof (buf)));
} }
@ -843,8 +817,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
{ {
char buf[NEXTHOP_STRLEN]; char buf[NEXTHOP_STRLEN];
zlog_debug zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)",
("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)",
__PRETTY_FUNCTION__, ifp->name, nexthop->ifindex, __PRETTY_FUNCTION__, ifp->name, nexthop->ifindex,
nexthop2str (nexthop, buf, sizeof (buf))); nexthop2str (nexthop, buf, sizeof (buf)));
} }
@ -887,8 +860,7 @@ pim_parse_nexthop_update (int command, struct zclient *zclient,
{ {
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str (&p, buf, sizeof (buf)); prefix2str (&p, buf, sizeof (buf));
zlog_debug zlog_debug ("%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d",
("%s: NHT Update for %s nexthop_num:%d pim nexthop_num %d vrf:%d up %d rp %d",
__PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id, __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id,
listcount (pnc->upstream_list), listcount (pnc->rp_list)); listcount (pnc->upstream_list), listcount (pnc->rp_list));
} }
@ -925,10 +897,8 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
__PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time); __PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time);
} }
memset (nexthop_tab, 0, memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM);
sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); num_ifindex = zclient_lookup_nexthop (nexthop_tab, MULTIPATH_NUM, addr,
num_ifindex =
zclient_lookup_nexthop (nexthop_tab, MULTIPATH_NUM, addr,
PIM_NEXTHOP_LOOKUP_MAX); PIM_NEXTHOP_LOOKUP_MAX);
if (num_ifindex < 1) if (num_ifindex < 1)
{ {
@ -939,13 +909,13 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
return -1; return -1;
} }
//If PIM ECMP enable then choose ECMP path //If PIM ECMP enable then choose ECMP path.
if (qpim_ecmp_enable) if (qpim_ecmp_enable)
{ {
hash_val = pim_compute_ecmp_hash (src, grp); hash_val = pim_compute_ecmp_hash (src, grp);
mod_val = hash_val % num_ifindex; mod_val = hash_val % num_ifindex;
if (PIM_DEBUG_TRACE) if (PIM_DEBUG_TRACE)
zlog_debug ("%s: hash_val %u mod_val %u ", zlog_debug ("%s: hash_val %u mod_val %u",
__PRETTY_FUNCTION__, hash_val, mod_val); __PRETTY_FUNCTION__, hash_val, mod_val);
} }
@ -960,8 +930,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
{ {
char addr_str[INET_ADDRSTRLEN]; char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str));
zlog_debug zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)",
("%s %s: could not find interface for ifindex %d (address %s)",
__FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str);
} }
if (i == mod_val) if (i == mod_val)
@ -976,8 +945,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
{ {
char addr_str[INET_ADDRSTRLEN]; char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str));
zlog_debug zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str);
} }
if (i == mod_val) if (i == mod_val)
@ -987,8 +955,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
} }
if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) if (neighbor_needed && !pim_if_connected_to_source (ifp, addr))
{ {
nbr = nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4);
pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4);
if (PIM_DEBUG_PIM_TRACE_DETAIL) if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr);
if (!nbr && !if_is_loopback (ifp)) if (!nbr && !if_is_loopback (ifp))
@ -1001,8 +968,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
char addr_str[INET_ADDRSTRLEN]; char addr_str[INET_ADDRSTRLEN];
pim_inet4_dump ("<addr?>", addr, addr_str, pim_inet4_dump ("<addr?>", addr, addr_str,
sizeof (addr_str)); sizeof (addr_str));
zlog_debug zlog_debug ("%s: NBR not found on input interface %s (RPF for source %s)",
("%s: NBR not found on input interface %s (RPF for source %s)",
__PRETTY_FUNCTION__, ifp->name, addr_str); __PRETTY_FUNCTION__, ifp->name, addr_str);
} }
continue; continue;
@ -1018,8 +984,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
pim_addr_dump ("<nexthop?>", &nexthop_tab[i].nexthop_addr, pim_addr_dump ("<nexthop?>", &nexthop_tab[i].nexthop_addr,
nexthop_str, sizeof (nexthop_str)); nexthop_str, sizeof (nexthop_str));
pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str));
zlog_debug zlog_debug ("%s %s: found nhop %s for addr %s interface %s metric %d dist %d",
("%s %s: found nexthop %s for addr %s interface %s metric=%d pref=%d",
__FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str, __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str,
ifp->name, nexthop_tab[i].route_metric, ifp->name, nexthop_tab[i].route_metric,
nexthop_tab[i].protocol_distance); nexthop_tab[i].protocol_distance);
@ -1041,3 +1006,67 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
else else
return -1; return -1;
} }
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_TRACE)
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;
}

View file

@ -65,5 +65,8 @@ int pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr,
int neighbor_needed); int neighbor_needed);
void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc,
int command); int command);
int pim_update_rp_nh (struct pim_nexthop_cache *pnc);
void pim_resolve_upstream_nh (struct prefix *nht_p); void pim_resolve_upstream_nh (struct prefix *nht_p);
int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr,
struct prefix *src, struct prefix *grp);
#endif #endif

View file

@ -164,6 +164,7 @@ struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
} }
c_oil->oil.mfcc_parent = input_vif_index; c_oil->oil.mfcc_parent = input_vif_index;
++c_oil->oil_ref_count; ++c_oil->oil_ref_count;
c_oil->up = pim_upstream_find(sg); //channel might be present prior to upstream
return c_oil; return c_oil;
} }
@ -188,6 +189,7 @@ struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
c_oil->oil.mfcc_parent = input_vif_index; c_oil->oil.mfcc_parent = input_vif_index;
c_oil->oil_ref_count = 1; c_oil->oil_ref_count = 1;
c_oil->installed = 0; c_oil->installed = 0;
c_oil->up = pim_upstream_find(sg);
listnode_add_sort(pim_channel_oil_list, c_oil); listnode_add_sort(pim_channel_oil_list, c_oil);
@ -204,6 +206,7 @@ void pim_channel_oil_del(struct channel_oil *c_oil)
* into pim_channel_oil_free() because the later is * into pim_channel_oil_free() because the later is
* called by list_delete_all_node() * called by list_delete_all_node()
*/ */
c_oil->up = NULL;
listnode_delete(pim_channel_oil_list, c_oil); listnode_delete(pim_channel_oil_list, c_oil);
hash_release (pim_channel_oil_hash, c_oil); hash_release (pim_channel_oil_hash, c_oil);

View file

@ -79,6 +79,7 @@ struct channel_oil {
time_t oif_creation[MAXVIFS]; time_t oif_creation[MAXVIFS];
uint32_t oif_flags[MAXVIFS]; uint32_t oif_flags[MAXVIFS];
struct channel_counts cc; struct channel_counts cc;
struct pim_upstream *up;
}; };
extern struct list *pim_channel_oil_list; extern struct list *pim_channel_oil_list;

View file

@ -281,7 +281,7 @@ pim_rp_check_interfaces (struct rp_info *rp_info)
int int
pim_rp_new (const char *rp, const char *group_range, const char *plist) pim_rp_new (const char *rp, const char *group_range, const char *plist)
{ {
int result; int result = 0;
struct rp_info *rp_info; struct rp_info *rp_info;
struct rp_info *rp_all; struct rp_info *rp_all;
struct prefix group_all; struct prefix group_all;
@ -759,7 +759,7 @@ pim_rp_g (struct in_addr group)
char buf1[PREFIX2STR_BUFFER]; char buf1[PREFIX2STR_BUFFER];
prefix2str (&nht_p, buf, sizeof (buf)); prefix2str (&nht_p, buf, sizeof (buf));
prefix2str (&g, buf1, sizeof (buf1)); prefix2str (&g, buf1, sizeof (buf1));
zlog_debug ("%s: NHT nexthop cache not found for RP %s grp %s", zlog_debug ("%s: Nexthop cache not found for RP %s grp %s register with Zebra NHT",
__PRETTY_FUNCTION__, buf, buf1); __PRETTY_FUNCTION__, buf, buf1);
} }
pim_rpf_set_refresh_time (); pim_rpf_set_refresh_time ();
@ -972,8 +972,7 @@ pim_resolve_rp_nh (void)
{ {
if (nh_node->gate.ipv4.s_addr == 0) if (nh_node->gate.ipv4.s_addr == 0)
{ {
nbr = nbr = pim_neighbor_find_if (if_lookup_by_index
pim_neighbor_find_if (if_lookup_by_index
(nh_node->ifindex, VRF_DEFAULT)); (nh_node->ifindex, VRF_DEFAULT));
if (nbr) if (nbr)
{ {
@ -982,14 +981,15 @@ pim_resolve_rp_nh (void)
{ {
char str[PREFIX_STRLEN]; char str[PREFIX_STRLEN];
char str1[INET_ADDRSTRLEN]; char str1[INET_ADDRSTRLEN];
struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex,
VRF_DEFAULT);
pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, pim_inet4_dump ("<nht_nbr?>", nbr->source_addr,
str1, sizeof (str1)); str1, sizeof (str1));
pim_addr_dump ("<nht_addr?>", &nht_p, str, pim_addr_dump ("<nht_addr?>", &nht_p, str,
sizeof (str)); sizeof (str));
zlog_debug zlog_debug ("%s: addr %s new nexthop addr %s interface %s",
("%s: addr %s new nexthop addr %s ifindex %d ",
__PRETTY_FUNCTION__, str, str1, __PRETTY_FUNCTION__, str, str1,
nh_node->ifindex); ifp1->name);
} }
} }
} }

View file

@ -162,8 +162,9 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
struct prefix nht_p; struct prefix nht_p;
if (PIM_DEBUG_TRACE) if (PIM_DEBUG_TRACE)
zlog_debug ("%s(%s): Delete %s ref count: %d, flags: %d (Pre decrement)", zlog_debug ("%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)",
__PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags); __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags,
up->channel_oil->oil_ref_count);
--up->ref_count; --up->ref_count;

View file

@ -53,7 +53,6 @@
static struct zclient *zclient = NULL; static struct zclient *zclient = NULL;
static int fib_lookup_if_vif_index(struct in_addr addr);
/* Router-id update message from zebra. */ /* Router-id update message from zebra. */
static int pim_router_id_update_zebra(int command, struct zclient *zclient, static int pim_router_id_update_zebra(int command, struct zclient *zclient,
@ -469,7 +468,28 @@ pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index)
if (in_vif_index) if (in_vif_index)
input_iface_vif_index = in_vif_index; input_iface_vif_index = in_vif_index;
else else
input_iface_vif_index = fib_lookup_if_vif_index (vif_source); {
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 (input_iface_vif_index < 1)
{ {
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
@ -557,12 +577,25 @@ void pim_scan_oil()
struct listnode *node; struct listnode *node;
struct listnode *nextnode; struct listnode *nextnode;
struct channel_oil *c_oil; struct channel_oil *c_oil;
ifindex_t ifindex;
int vif_index = 0;
qpim_scan_oil_last = pim_time_monotonic_sec(); qpim_scan_oil_last = pim_time_monotonic_sec();
++qpim_scan_oil_events; ++qpim_scan_oil_events;
for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil))
pim_scan_individual_oil (c_oil, 0); {
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) static int on_rpf_cache_refresh(struct thread *t)
@ -699,67 +732,6 @@ void igmp_anysource_forward_stop(struct igmp_group *group)
igmp_source_forward_stop (source); igmp_source_forward_stop (source);
} }
static int fib_lookup_if_vif_index(struct in_addr addr)
{
struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
int num_ifindex;
int vif_index;
ifindex_t first_ifindex;
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;
}
first_ifindex = nexthop_tab[0].ifindex;
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: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
__FILE__, __PRETTY_FUNCTION__,
num_ifindex, addr_str, first_ifindex);
}
/* debug warning only, do not return */
}
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;
}
static void static void
igmp_source_forward_reevaluate_one(struct igmp_source *source) igmp_source_forward_reevaluate_one(struct igmp_source *source)
{ {
@ -873,6 +845,7 @@ void igmp_source_forward_start(struct igmp_source *source)
int ret = 0; int ret = 0;
struct pim_nexthop_cache out_pnc; struct pim_nexthop_cache out_pnc;
struct pim_nexthop nexthop; struct pim_nexthop nexthop;
struct pim_upstream *up = NULL;
if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp)) if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp))
return; return;
@ -883,20 +856,23 @@ void igmp_source_forward_start(struct igmp_source *source)
nht_p.u.prefix4 = vif_source; nht_p.u.prefix4 = vif_source;
memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); 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 ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
{ {
if (out_pnc.nexthop_num) if (out_pnc.nexthop_num)
{ {
src.family = AF_INET; up = pim_upstream_find (&sg);
src.prefixlen = IPV4_MAX_BITLEN; memset (&nexthop, 0, sizeof (struct pim_nexthop));
src.u.prefix4 = vif_source; //RP or Src address if (up)
grp.family = AF_INET; memcpy (&nexthop, &up->rpf.source_nexthop, sizeof (struct pim_nexthop));
grp.prefixlen = IPV4_MAX_BITLEN;
grp.u.prefix4 = sg.grp;
memset (&nexthop, 0, sizeof (nexthop));
//Compute PIM RPF using Cached nexthop //Compute PIM RPF using Cached nexthop
pim_ecmp_nexthop_search (&out_pnc, &nexthop, pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0);
&src, &grp, 0);
if (nexthop.interface) if (nexthop.interface)
input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex); input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex);
} }
@ -914,7 +890,7 @@ void igmp_source_forward_start(struct igmp_source *source)
} }
} }
else else
input_iface_vif_index = fib_lookup_if_vif_index(vif_source); input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp);
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
{ {
@ -1095,7 +1071,6 @@ void pim_forward_start(struct pim_ifchannel *ch)
struct prefix nht_p, src, grp; struct prefix nht_p, src, grp;
int ret = 0; int ret = 0;
struct pim_nexthop_cache out_pnc; struct pim_nexthop_cache out_pnc;
struct pim_nexthop nexthop;
/* Register addr with Zebra NHT */ /* Register addr with Zebra NHT */
nht_p.family = AF_INET; nht_p.family = AF_INET;
@ -1106,8 +1081,7 @@ void pim_forward_start(struct pim_ifchannel *ch)
grp.u.prefix4 = up->sg.grp; grp.u.prefix4 = up->sg.grp;
memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
if ((ret = if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
{ {
if (out_pnc.nexthop_num) if (out_pnc.nexthop_num)
{ {
@ -1117,11 +1091,14 @@ void pim_forward_start(struct pim_ifchannel *ch)
grp.family = AF_INET; grp.family = AF_INET;
grp.prefixlen = IPV4_MAX_BITLEN; grp.prefixlen = IPV4_MAX_BITLEN;
grp.u.prefix4 = up->sg.grp; grp.u.prefix4 = up->sg.grp;
memset (&nexthop, 0, sizeof (nexthop));
//Compute PIM RPF using Cached nexthop //Compute PIM RPF using Cached nexthop
pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0); if (pim_ecmp_nexthop_search (&out_pnc, &up->rpf.source_nexthop, &src, &grp, 0) == 0)
input_iface_vif_index = input_iface_vif_index = pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop.interface->ifindex);
pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex); else
{
if (PIM_DEBUG_TRACE)
zlog_debug ("%s: Nexthop selection failed for %s ", __PRETTY_FUNCTION__, up->sg_str);
}
} }
else else
{ {
@ -1137,7 +1114,7 @@ void pim_forward_start(struct pim_ifchannel *ch)
} }
} }
else else
input_iface_vif_index = fib_lookup_if_vif_index (up->upstream_addr); input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(up->upstream_addr, &src, &grp);
if (input_iface_vif_index < 1) if (input_iface_vif_index < 1)
{ {
@ -1153,8 +1130,10 @@ void pim_forward_start(struct pim_ifchannel *ch)
} }
if (PIM_DEBUG_TRACE) if (PIM_DEBUG_TRACE)
{ {
zlog_debug ("%s: NHT entry %s update channel_oil vif_index %d ", struct interface *in_intf = pim_if_find_by_vif_index (input_iface_vif_index);
__PRETTY_FUNCTION__, up->sg_str, 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); up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index);
if (!up->channel_oil) if (!up->channel_oil)