diff options
Diffstat (limited to 'pimd/pim_nht.c')
| -rw-r--r-- | pimd/pim_nht.c | 57 |
1 files changed, 48 insertions, 9 deletions
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index b6cd1a7d11..9b5379384c 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -39,6 +39,7 @@ #include "pim_jp_agg.h" #include "pim_zebra.h" #include "pim_zlookup.h" +#include "pim_rp.h" /** * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister @@ -170,6 +171,8 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr, struct pim_nexthop_cache *pnc = NULL; struct pim_nexthop_cache lookup; struct zclient *zclient = NULL; + struct listnode *upnode = NULL; + struct pim_upstream *upstream = NULL; zclient = pim_zebra_zclient_get(); @@ -177,8 +180,30 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr, lookup.rpf.rpf_addr = *addr; pnc = hash_lookup(pim->rpf_hash, &lookup); if (pnc) { - if (rp) + if (rp) { + /* Release the (*, G)upstream from pnc->upstream_hash, + * whose Group belongs to the RP getting deleted + */ + for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, + upstream)) { + struct prefix grp; + struct rp_info *trp_info; + + if (upstream->sg.src.s_addr != INADDR_ANY) + continue; + + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = upstream->sg.grp; + + trp_info = pim_rp_find_match_group(pim, &grp); + if (trp_info == rp) + hash_release(pnc->upstream_hash, + upstream); + } listnode_delete(pnc->rp_list, rp); + } + if (up) hash_release(pnc->upstream_hash, up); @@ -207,6 +232,17 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr, } } +void pim_rp_nexthop_del(struct rp_info *rp_info) +{ + rp_info->rp.source_nexthop.interface = NULL; + rp_info->rp.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = + PIM_NET_INADDR_ANY; + rp_info->rp.source_nexthop.mrib_metric_preference = + router->infinite_assert_metric.metric_preference; + rp_info->rp.source_nexthop.mrib_route_metric = + router->infinite_assert_metric.route_metric; +} + /* Update RP nexthop info based on Nexthop update received from Zebra.*/ static void pim_update_rp_nh(struct pim_instance *pim, struct pim_nexthop_cache *pnc) @@ -220,9 +256,11 @@ static void pim_update_rp_nh(struct pim_instance *pim, continue; // Compute PIM RPF using cached nexthop - pim_ecmp_nexthop_search(pim, pnc, &rp_info->rp.source_nexthop, - &rp_info->rp.rpf_addr, &rp_info->group, - 1); + if (!pim_ecmp_nexthop_search(pim, pnc, + &rp_info->rp.source_nexthop, + &rp_info->rp.rpf_addr, &rp_info->group, + 1)) + pim_rp_nexthop_del(rp_info); } } @@ -278,12 +316,12 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg) old.source_nexthop.interface = up->rpf.source_nexthop.interface; rpf_result = pim_rpf_update(pim, up, &old, 0); if (rpf_result == PIM_RPF_FAILURE) { - pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__); + pim_upstream_rpf_clear(pim, up); return HASHWALK_CONTINUE; } /* update kernel multicast forwarding cache (MFC) */ - if (up->channel_oil) { + if (up->rpf.source_nexthop.interface) { ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex; vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex); @@ -306,9 +344,10 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg) if (PIM_DEBUG_PIM_NHT) { zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s", - __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name, - old.source_nexthop.interface->name, - up->rpf.source_nexthop.interface->name); + __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name, + old.source_nexthop.interface + ? old.source_nexthop.interface->name : "Unknwon", + up->rpf.source_nexthop.interface->name); } return HASHWALK_CONTINUE; |
