diff options
Diffstat (limited to 'pimd/pim_upstream.c')
| -rw-r--r-- | pimd/pim_upstream.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 8fa7b7cf96..556d25b822 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -17,6 +17,7 @@ #include "jhash.h" #include "wheel.h" #include "network.h" +#include "frrdistance.h" #include "pimd.h" #include "pim_pim.h" @@ -181,7 +182,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim, if (PIM_DEBUG_PIM_TRACE) zlog_debug( - "%s(%s): Delete %s[%s] ref count: %d , flags: %d c_oil ref count %d (Pre decrement)", + "%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)", __func__, name, up->sg_str, pim->vrf->name, up->ref_count, up->flags, up->channel_oil->oil_ref_count); @@ -662,10 +663,9 @@ void pim_upstream_update_use_rpt(struct pim_upstream *up, new_use_rpt = !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags); if (old_use_rpt != new_use_rpt) { if (PIM_DEBUG_PIM_EVENTS) - zlog_debug("%s switched from %s to %s", - up->sg_str, - old_use_rpt?"RPT":"SPT", - new_use_rpt?"RPT":"SPT"); + zlog_debug("%s switched from %s to %s", up->sg_str, + old_use_rpt ? "RPT" : "SPT", + new_use_rpt ? "RPT" : "SPT"); if (update_mroute) pim_upstream_mroute_add(up->channel_oil, __func__); } @@ -904,14 +904,21 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, false /*update_mroute*/); pim_upstream_mroute_iif_update(up->channel_oil, __func__); - if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)) + if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)) { + /* + * Set the right RPF so that future changes will + * be right + */ + (void)pim_rpf_update(pim, up, NULL, __func__); pim_upstream_keep_alive_timer_start( up, pim->keep_alive_time); + } } else if (!pim_addr_is_any(up->upstream_addr)) { pim_upstream_update_use_rpt(up, false /*update_mroute*/); rpf_result = pim_rpf_update(pim, up, NULL, __func__); if (rpf_result == PIM_RPF_FAILURE) { + up->channel_oil->oil_inherited_rescan = 1; if (PIM_DEBUG_PIM_TRACE) zlog_debug( "%s: Attempting to create upstream(%s), Unable to RPF for source", @@ -1713,6 +1720,7 @@ static void pim_upstream_register_stop_timer(struct event *t) zlog_debug("%s: up %s RPF is not present", __func__, up->sg_str); up->reg_state = PIM_REG_NOINFO; + PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags); return; } @@ -1936,6 +1944,40 @@ void pim_upstream_terminate(struct pim_instance *pim) wheel_delete(pim->upstream_sg_wheel); pim->upstream_sg_wheel = NULL; } +bool pim_sg_is_reevaluate_oil_req(struct pim_instance *pim, + struct pim_upstream *up) +{ + struct pim_interface *pim_ifp = NULL; + + /* + * Attempt to retrieve the PIM interface information if the RPF + * interface is present + */ + if (up->rpf.source_nexthop.interface) { + pim_ifp = up->rpf.source_nexthop.interface->info; + } else { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: up %s RPF is not present", __func__, + up->sg_str); + } + } + + /* + * Determine if a reevaluation of the outgoing interface list (OIL) is + * required. This may be necessary in scenarios such as MSDP where the + * RP role for a group changes from secondary to primary. In such cases, + * SGRpt may receive a prune, resulting in an S,G entry with a NULL OIL. + * The S,G upstream should then inherit the OIL from *,G, which is + * particularly important for VXLAN setups. + */ + if (up->channel_oil->oil_inherited_rescan || + (pim_ifp && I_am_RP(pim_ifp->pim, up->sg.grp)) || + pim_upstream_empty_inherited_olist(up)) { + return true; + } + + return false; +} bool pim_upstream_equal(const void *arg1, const void *arg2) { @@ -1964,6 +2006,7 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up) struct channel_oil *c_oil = up->channel_oil; struct interface *ifp = up->rpf.source_nexthop.interface; struct pim_interface *pim_ifp; + struct pim_instance *pim = up->channel_oil->pim; /* "iif == RPF_interface(S)" check is not easy to do as the info * we get from the kernel/ASIC is really a "lookup/key hit". @@ -1974,7 +2017,7 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up) return false; pim_ifp = ifp->info; - if (pim_ifp->mroute_vif_index != *oil_parent(c_oil)) + if (pim_ifp->mroute_vif_index != *oil_incoming_vif(c_oil)) return false; if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, @@ -1983,8 +2026,9 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up) } if ((up->join_state == PIM_UPSTREAM_JOINED) - && !pim_upstream_empty_inherited_olist(up)) { - return true; + && !pim_upstream_empty_inherited_olist(up)) { + if (I_am_RP(pim, up->sg.grp)) + return true; } return false; @@ -2056,7 +2100,7 @@ static void pim_upstream_sg_running(void *arg) // No packet can have arrived here if this is the case if (!up->channel_oil->installed) { if (PIM_DEBUG_TRACE) - zlog_debug("%s: %s%s is not installed in mroute", + zlog_debug("%s: %s[%s] is not installed in mroute", __func__, up->sg_str, pim->vrf->name); return; } @@ -2069,7 +2113,7 @@ static void pim_upstream_sg_running(void *arg) * only doing this at this point in time * to get us up and working for the moment */ - if (up->channel_oil->oil_inherited_rescan) { + if (pim_sg_is_reevaluate_oil_req(pim, up)) { if (PIM_DEBUG_TRACE) zlog_debug( "%s: Handling unscanned inherited_olist for %s[%s]", |
