diff options
-rw-r--r-- | pimd/pim_ifchannel.c | 23 | ||||
-rw-r--r-- | pimd/pim_ifchannel.h | 2 | ||||
-rw-r--r-- | pimd/pim_join.c | 39 | ||||
-rw-r--r-- | pimd/pim_rpf.c | 13 | ||||
-rw-r--r-- | pimd/pim_upstream.c | 5 |
5 files changed, 48 insertions, 34 deletions
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index d46cc70b0..6f5e8f149 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -1287,7 +1287,7 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp) * we get End of Message */ 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 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)) { /* 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 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)) { 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 (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_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)) continue; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 3ffb9190f..4c804cc72 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -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_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); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 828781a46..2da0b9935 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -215,7 +215,8 @@ int pim_joinprune_recv(struct interface *ifp, uint16_t msg_num_joined_sources; uint16_t msg_num_pruned_sources; 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)); 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) { - ch = pim_ifchannel_find (ifp, &sg); - if (ch) - pim_ifchannel_set_star_g_join_state (ch, 0, msg_source_flags, 1); + starg_alone = 1; + starg_ch = pim_ifchannel_find (ifp, &sg); + 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; } - buf += addr_offset; + sg_ch = pim_ifchannel_find (ifp, &sg); + buf += addr_offset; + starg_alone = 0; recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, &sg, 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) - pim_ifchannel_set_star_g_join_state (ch, 1, msg_source_flags, 0); - ch = NULL; + if (starg_ch) + pim_ifchannel_set_star_g_join_state (starg_ch, 1, msg_source_flags, 0, starg_alone); + starg_ch = NULL; } /* scan groups */ return 0; @@ -502,6 +521,10 @@ int pim_joinprune_send(struct pim_rpf *rpf, packet_size += 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; if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255) { diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index f46ebfb97..d16106dec 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -244,17 +244,18 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, { return PIM_RPF_FAILURE; } - } + } rpf->rpf_addr.family = AF_INET; rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); - 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", + 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", __FILE__, __PRETTY_FUNCTION__, up->sg_str); - /* warning only */ - } + /* warning only */ + } /* detect change in pim_nexthop */ if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 6fadfc2f2..af9c3913a 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -582,8 +582,9 @@ pim_upstream_switch(struct pim_upstream *up, if (old_state == PIM_UPSTREAM_JOINED) pim_msdp_up_join_state_changed(up); - /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT */ - if (pim_upstream_is_sg_rpt(up) && up->parent) + /* 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(up->sg.grp)) { if (PIM_DEBUG_PIM_TRACE_DETAIL) zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__, |