if (up->ref_count >= 1)
return up;
+ if (PIM_DEBUG_TRACE)
+ zlog_debug(
+ "pim_upstream free vrf:%s %s flags 0x%x",
+ pim->vrf->name, up->sg_str, up->flags);
+
THREAD_OFF(up->t_ka_timer);
THREAD_OFF(up->t_rs_timer);
THREAD_OFF(up->t_msdp_reg_timer);
up->rpf.rpf_addr.u.prefix4);
if (nbr)
- pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
+ pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
pim_jp_agg_upstream_verification(up, false);
}
}
if (nbr)
- pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1);
+ pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1, nbr);
else {
THREAD_OFF(up->t_join_timer);
thread_add_timer(router->master, on_join_timer, up,
join_timer_start(up);
}
}
+ if (old_state != new_state)
+ pim_upstream_update_use_rpt(up, true /*update_mroute*/);
} else {
+ bool old_use_rpt;
+ bool new_use_rpt;
+ bool send_xg_jp = false;
forward_off(up);
if (old_state == PIM_UPSTREAM_JOINED)
pim_msdp_up_join_state_changed(pim, up);
+ if (old_state != new_state) {
+ old_use_rpt =
+ !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags);
+ pim_upstream_update_use_rpt(up, true /*update_mroute*/);
+ new_use_rpt =
+ !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags);
+ if (new_use_rpt &&
+ (new_use_rpt != old_use_rpt) &&
+ up->parent)
+ /* we have decided to switch from the SPT back
+ * to the RPT which means we need to cancel
+ * any previously sent SGrpt prunes immediately
+ */
+ send_xg_jp = true;
+ }
+
/* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards
RP.
If I am RP for G then send S,G prune to its IIF. */
- if (pim_upstream_is_sg_rpt(up) && up->parent
- && !I_am_RP(pim, up->sg.grp)) {
+ if (pim_upstream_is_sg_rpt(up) && up->parent &&
+ !I_am_RP(pim, up->sg.grp))
+ send_xg_jp = true;
+ else
+ pim_jp_agg_single_upstream_send(&up->rpf, up,
+ 0 /* prune */);
+
+ if (send_xg_jp) {
if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug(
- "%s: *,G IIF %s S,G IIF %s ",
- __PRETTY_FUNCTION__,
+ "re-join RPT; *,G IIF %s S,G IIF %s ",
up->parent->rpf.source_nexthop.interface ?
up->parent->rpf.source_nexthop.interface->name
: "Unknown",
pim_jp_agg_single_upstream_send(&up->parent->rpf,
up->parent,
1 /* (W,G) Join */);
- } else
- pim_jp_agg_single_upstream_send(&up->rpf, up,
- 0 /* prune */);
+ }
join_timer_stop(up);
}
-
- if (old_state != new_state)
- pim_upstream_update_use_rpt(up, true /*update_mroute*/);
}
int pim_upstream_compare(void *arg1, void *arg2)
pim_upstream_fill_static_iif(up, incoming);
pim_ifp = up->rpf.source_nexthop.interface->info;
assert(pim_ifp);
+ pim_upstream_update_use_rpt(up,
+ false /*update_mroute*/);
pim_upstream_mroute_iif_update(up->channel_oil, __func__);
if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags))
pim_upstream_keep_alive_timer_start(
up, pim->keep_alive_time);
} else if (up->upstream_addr.s_addr != INADDR_ANY) {
+ pim_upstream_update_use_rpt(up,
+ false /*update_mroute*/);
rpf_result = pim_rpf_update(pim, up, NULL, __func__);
if (rpf_result == PIM_RPF_FAILURE) {
if (PIM_DEBUG_PIM_TRACE)
}
if (up->rpf.source_nexthop.interface) {
- pim_ifp = up->rpf.source_nexthop.interface->info;
- if (pim_ifp)
- pim_upstream_mroute_iif_update(up->channel_oil,
- __func__);
+ pim_upstream_mroute_iif_update(up->channel_oil,
+ __func__);
}
- pim_upstream_update_use_rpt(up,
- false /*update_mroute*/);
}
listnode_add_sort(pim->upstream_list, up);
pim_upstream_update_use_rpt(up, true /*update_mroute*/);
}
+ /* re-eval joinDesired; clearing peer-msdp-sa flag can
+ * cause JD to change
+ */
+ if (!PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags) &&
+ PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags)) {
+ PIM_UPSTREAM_FLAG_SET_SRC_MSDP(up->flags);
+ pim_upstream_update_join_desired(up->pim, up);
+ }
+
up->flags |= flags;
++up->ref_count;
if (PIM_DEBUG_PIM_TRACE)
return true;
}
+
+static inline bool pim_upstream_is_msdp_peer_sa(struct pim_upstream *up)
+{
+ return PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags);
+}
+
/*
* bool JoinDesired(*,G) {
* if (immediate_olist(*,G) != NULL)
empty_inh_oil = pim_upstream_empty_inherited_olist(up);
if (!empty_inh_oil &&
(pim_upstream_is_kat_running(up) ||
- I_am_RP(pim, up->sg.grp)))
+ pim_upstream_is_msdp_peer_sa(up)))
return true;
return false;
zlog_debug(
"%s: Upstream %s without a path to send join, checking",
__PRETTY_FUNCTION__, up->sg_str);
- old.source_nexthop.interface = up->rpf.source_nexthop.interface;
+ old.source_nexthop.interface =
+ up->rpf.source_nexthop.interface;
rpf_result = pim_rpf_update(pim, up, &old, __func__);
- if (rpf_result == PIM_RPF_CHANGED)
+ if (rpf_result == PIM_RPF_CHANGED ||
+ (rpf_result == PIM_RPF_FAILURE &&
+ old.source_nexthop.interface))
pim_zebra_upstream_rpf_changed(pim, up, &old);
/* update kernel multicast forwarding cache (MFC) */
- pim_upstream_mroute_iif_update(up->channel_oil, __func__);
+ pim_upstream_mroute_iif_update(up->channel_oil,
+ __func__);
}
}
pim_zebra_update_all_interfaces(pim);
if (pim_ifp->mroute_vif_index != c_oil->oil.mfcc_parent)
return false;
- if (up->rpf.source_nexthop.interface &&
- pim_if_connected_to_source(up->rpf.source_nexthop.interface,
+ if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
up->sg.src)) {
return true;
}