From c692bd2ad42e941d0d63a149daaed1a331d47cd0 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Fri, 15 Nov 2019 12:01:46 -0800 Subject: [PATCH] pimd: send an immediate XG JP message when switching from SPT to RPT Today we are only pruning the SPT when (S,G) upstream entry switches from Joined toNotJoined. This leaves the source still pruned along the RPT till the next periodic XG join-prune is sent to the RPF(RP). Traffic from the source will be blackholed for this duration. To prevent that we need send a new JP message to RPF(RP) immediately. Signed-off-by: Anuradha Karuppiah --- pimd/pim_jp_agg.c | 8 ++++---- pimd/pim_upstream.c | 41 +++++++++++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index e1473bfe3b..5f9e166810 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -338,10 +338,10 @@ void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, static bool first = true; /* skip JP upstream messages if source is directly connected */ - if (!up || !rpf->source_nexthop.interface || pim_if_connected_to_source( - rpf->source_nexthop - .interface, - up->sg.src)) + if (!up || !rpf->source_nexthop.interface || + pim_if_connected_to_source(rpf->source_nexthop.interface, + up->sg.src) || + if_is_loopback_or_vrf(rpf->source_nexthop.interface)) return; if (first) { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 53da58e8fe..4d0a63b915 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -696,21 +696,47 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *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", @@ -720,14 +746,9 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up, 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)