forked from Mirror/frr
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join towards FHR, unset SGRpt flag from channel, add (*,G) oif to (S,G) entry. -Add I am not RP check to triger SGRpt on *,G path otherwise, send S,G Prune on SPT path from RP to FHR upon receving *,G Prune. -Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G. Testing Done: pim-smoke Ran 95 tests in 11790.552s FAILED (SKIP=10, failures=4) Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
This commit is contained in:
parent
f1deac618b
commit
ee22bbae78
|
@ -1287,7 +1287,7 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp)
|
||||||
* we get End of Message
|
* we get End of Message
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join)
|
pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone)
|
||||||
{
|
{
|
||||||
struct pim_ifchannel *child;
|
struct pim_ifchannel *child;
|
||||||
struct listnode *ch_node;
|
struct listnode *ch_node;
|
||||||
|
@ -1302,10 +1302,11 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t
|
||||||
for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child))
|
for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child))
|
||||||
{
|
{
|
||||||
/* Only *,G Join received and no (SG-RPT) prune.
|
/* Only *,G Join received and no (SG-RPT) prune.
|
||||||
|
eom = 1, only (W,G) join_alone is true, WC and RPT are set.
|
||||||
Scan all S,G associated to G and if any SG-RPT
|
Scan all S,G associated to G and if any SG-RPT
|
||||||
remove the SG-RPT flag.
|
remove the SG-RPT flag.
|
||||||
*/
|
*/
|
||||||
if (join && (source_flags & PIM_RPT_BIT_MASK) &&
|
if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) &&
|
||||||
(source_flags & PIM_WILDCARD_BIT_MASK))
|
(source_flags & PIM_WILDCARD_BIT_MASK))
|
||||||
{
|
{
|
||||||
if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
|
if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
|
||||||
|
@ -1316,25 +1317,13 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t
|
||||||
if (up)
|
if (up)
|
||||||
{
|
{
|
||||||
if (PIM_DEBUG_TRACE)
|
if (PIM_DEBUG_TRACE)
|
||||||
zlog_debug ("%s: clearing SGRpt flag, add inherit oif to up %s ", __PRETTY_FUNCTION__, up->sg_str);
|
zlog_debug ("%s: SGRpt flag is cleared, add inherit oif to up %s",
|
||||||
|
__PRETTY_FUNCTION__, up->sg_str);
|
||||||
pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
|
pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
|
||||||
|
pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, child, PIM_IFJOIN_JOIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Received SG-RPT Prune delete oif from S,G */
|
|
||||||
else if (join == 0 && (source_flags & PIM_RPT_BIT_MASK) &&
|
|
||||||
!(source_flags & PIM_WILDCARD_BIT_MASK))
|
|
||||||
{
|
|
||||||
struct pim_upstream *up = child->upstream;
|
|
||||||
|
|
||||||
PIM_IF_FLAG_SET_S_G_RPT(child->flags);
|
|
||||||
if (up)
|
|
||||||
{
|
|
||||||
if (PIM_DEBUG_TRACE)
|
|
||||||
zlog_debug ("%s: SGRpt Set, del inherit oif from up %s", __PRETTY_FUNCTION__, up->sg_str);
|
|
||||||
pim_channel_del_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
|
if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -151,7 +151,7 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch);
|
||||||
void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch);
|
void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch);
|
||||||
|
|
||||||
void pim_ifchannel_scan_forward_start (struct interface *new_ifp);
|
void pim_ifchannel_scan_forward_start (struct interface *new_ifp);
|
||||||
void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join);
|
void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone);
|
||||||
|
|
||||||
int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2);
|
int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2);
|
||||||
|
|
||||||
|
|
|
@ -215,7 +215,8 @@ int pim_joinprune_recv(struct interface *ifp,
|
||||||
uint16_t msg_num_joined_sources;
|
uint16_t msg_num_joined_sources;
|
||||||
uint16_t msg_num_pruned_sources;
|
uint16_t msg_num_pruned_sources;
|
||||||
int source;
|
int source;
|
||||||
struct pim_ifchannel *ch = NULL;
|
struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL;
|
||||||
|
uint8_t starg_alone = 0;
|
||||||
|
|
||||||
memset (&sg, 0, sizeof (struct prefix_sg));
|
memset (&sg, 0, sizeof (struct prefix_sg));
|
||||||
addr_offset = pim_parse_addr_group (&sg,
|
addr_offset = pim_parse_addr_group (&sg,
|
||||||
|
@ -274,9 +275,10 @@ int pim_joinprune_recv(struct interface *ifp,
|
||||||
|
|
||||||
if (sg.src.s_addr == INADDR_ANY)
|
if (sg.src.s_addr == INADDR_ANY)
|
||||||
{
|
{
|
||||||
ch = pim_ifchannel_find (ifp, &sg);
|
starg_alone = 1;
|
||||||
if (ch)
|
starg_ch = pim_ifchannel_find (ifp, &sg);
|
||||||
pim_ifchannel_set_star_g_join_state (ch, 0, msg_source_flags, 1);
|
if (starg_ch)
|
||||||
|
pim_ifchannel_set_star_g_join_state (starg_ch, 0, msg_source_flags, 1, starg_alone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,16 +291,33 @@ int pim_joinprune_recv(struct interface *ifp,
|
||||||
return -8;
|
return -8;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf += addr_offset;
|
sg_ch = pim_ifchannel_find (ifp, &sg);
|
||||||
|
|
||||||
|
buf += addr_offset;
|
||||||
|
starg_alone = 0;
|
||||||
recv_prune(ifp, neigh, msg_holdtime,
|
recv_prune(ifp, neigh, msg_holdtime,
|
||||||
msg_upstream_addr.u.prefix4,
|
msg_upstream_addr.u.prefix4,
|
||||||
&sg,
|
&sg,
|
||||||
msg_source_flags);
|
msg_source_flags);
|
||||||
|
|
||||||
|
/* Received SG-RPT Prune delete oif from specific S,G */
|
||||||
|
if (starg_ch && sg_ch && (msg_source_flags & PIM_RPT_BIT_MASK)
|
||||||
|
&& !(msg_source_flags & PIM_WILDCARD_BIT_MASK))
|
||||||
|
{
|
||||||
|
struct pim_upstream *up = sg_ch->upstream;
|
||||||
|
PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags);
|
||||||
|
if (up)
|
||||||
|
{
|
||||||
|
if (PIM_DEBUG_TRACE)
|
||||||
|
zlog_debug ("%s: SGRpt flag is set, del inherit oif from up %s",
|
||||||
|
__PRETTY_FUNCTION__, up->sg_str);
|
||||||
|
pim_channel_del_oif (up->channel_oil, starg_ch->interface, PIM_OIF_FLAG_PROTO_STAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ch)
|
if (starg_ch)
|
||||||
pim_ifchannel_set_star_g_join_state (ch, 1, msg_source_flags, 0);
|
pim_ifchannel_set_star_g_join_state (starg_ch, 1, msg_source_flags, 0, starg_alone);
|
||||||
ch = NULL;
|
starg_ch = NULL;
|
||||||
} /* scan groups */
|
} /* scan groups */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -502,6 +521,10 @@ int pim_joinprune_send(struct pim_rpf *rpf,
|
||||||
packet_size += group_size;
|
packet_size += group_size;
|
||||||
pim_msg_build_jp_groups (grp, group, group_size);
|
pim_msg_build_jp_groups (grp, group, group_size);
|
||||||
|
|
||||||
|
if (PIM_DEBUG_PIM_TRACE)
|
||||||
|
zlog_debug ("%s: interface %s num_joins %u num_prunes %u", __PRETTY_FUNCTION__,
|
||||||
|
rpf->source_nexthop.interface->name, ntohs(grp->joins), ntohs (grp->prunes));
|
||||||
|
|
||||||
grp = (struct pim_jp_groups *)curr_ptr;
|
grp = (struct pim_jp_groups *)curr_ptr;
|
||||||
if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255)
|
if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255)
|
||||||
{
|
{
|
||||||
|
|
|
@ -244,17 +244,18 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
|
||||||
{
|
{
|
||||||
return PIM_RPF_FAILURE;
|
return PIM_RPF_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rpf->rpf_addr.family = AF_INET;
|
rpf->rpf_addr.family = AF_INET;
|
||||||
rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up);
|
rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up);
|
||||||
if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) {
|
if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA)
|
||||||
/* RPF'(S,G) not found */
|
{
|
||||||
zlog_debug("%s %s: RPF'%s not found: won't send join upstream",
|
/* RPF'(S,G) not found */
|
||||||
|
zlog_debug("%s %s: RPF'%s not found: won't send join upstream",
|
||||||
__FILE__, __PRETTY_FUNCTION__,
|
__FILE__, __PRETTY_FUNCTION__,
|
||||||
up->sg_str);
|
up->sg_str);
|
||||||
/* warning only */
|
/* warning only */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* detect change in pim_nexthop */
|
/* detect change in pim_nexthop */
|
||||||
if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) {
|
if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) {
|
||||||
|
|
|
@ -582,8 +582,9 @@ pim_upstream_switch(struct pim_upstream *up,
|
||||||
if (old_state == PIM_UPSTREAM_JOINED)
|
if (old_state == PIM_UPSTREAM_JOINED)
|
||||||
pim_msdp_up_join_state_changed(up);
|
pim_msdp_up_join_state_changed(up);
|
||||||
|
|
||||||
/* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT */
|
/* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards RP.
|
||||||
if (pim_upstream_is_sg_rpt(up) && up->parent)
|
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(up->sg.grp))
|
||||||
{
|
{
|
||||||
if (PIM_DEBUG_PIM_TRACE_DETAIL)
|
if (PIM_DEBUG_PIM_TRACE_DETAIL)
|
||||||
zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__,
|
zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__,
|
||||||
|
|
Loading…
Reference in a new issue