summaryrefslogtreecommitdiff
path: root/pimd/pim_upstream.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_upstream.c')
-rw-r--r--pimd/pim_upstream.c66
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]",