diff options
| author | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:03:14 +0200 |
|---|---|---|
| committer | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:04:07 +0200 |
| commit | d62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch) | |
| tree | 3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /pimd/pim_ifchannel.c | |
| parent | 888ac268a0077fc9ebd1218cec6ae472af0bfc40 (diff) | |
*: reindentreindent-master-after
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'`
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'pimd/pim_ifchannel.c')
| -rw-r--r-- | pimd/pim_ifchannel.c | 2254 |
1 files changed, 1137 insertions, 1117 deletions
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 021722dfc2..d4916518e7 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -43,34 +43,33 @@ #include "pim_upstream.h" #include "pim_ssm.h" -int -pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) +int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) { - struct pim_interface *pim_ifp1; - struct pim_interface *pim_ifp2; + struct pim_interface *pim_ifp1; + struct pim_interface *pim_ifp2; - pim_ifp1 = ch1->interface->info; - pim_ifp2 = ch2->interface->info; + pim_ifp1 = ch1->interface->info; + pim_ifp2 = ch2->interface->info; - if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) - return -1; + if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) + return -1; - if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) - return 1; + if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) + return 1; - if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) - return -1; + if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) + return -1; - if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) - return 1; + if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) + return 1; - if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) - return -1; + if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) + return -1; - if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) - return 1; + if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) + return 1; - return 0; + return 0; } /* @@ -78,20 +77,18 @@ pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) * remove the parent pointer from * those pointing at us */ -static void -pim_ifchannel_remove_children (struct pim_ifchannel *ch) +static void pim_ifchannel_remove_children(struct pim_ifchannel *ch) { - struct pim_ifchannel *child; + struct pim_ifchannel *child; - if (!ch->sources) - return; + if (!ch->sources) + return; - while (!list_isempty (ch->sources)) - { - child = listnode_head (ch->sources); - child->parent = NULL; - listnode_delete (ch->sources, child); - } + while (!list_isempty(ch->sources)) { + child = listnode_head(ch->sources); + child->parent = NULL; + listnode_delete(ch->sources, child); + } } /* @@ -99,284 +96,302 @@ pim_ifchannel_remove_children (struct pim_ifchannel *ch) * find all the children that would point * at us. */ -static void -pim_ifchannel_find_new_children (struct pim_ifchannel *ch) +static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp = ch->interface->info; - struct pim_ifchannel *child; - struct listnode *ch_node; - - // Basic Sanity that we are not being silly - if ((ch->sg.src.s_addr != INADDR_ANY) && - (ch->sg.grp.s_addr != INADDR_ANY)) - return; - - if ((ch->sg.src.s_addr == INADDR_ANY) && - (ch->sg.grp.s_addr == INADDR_ANY)) - return; - - for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) - { - if ((ch->sg.grp.s_addr != INADDR_ANY) && - (child->sg.grp.s_addr == ch->sg.grp.s_addr) && - (child != ch)) - { - child->parent = ch; - listnode_add_sort (ch->sources, child); + struct pim_interface *pim_ifp = ch->interface->info; + struct pim_ifchannel *child; + struct listnode *ch_node; + + // Basic Sanity that we are not being silly + if ((ch->sg.src.s_addr != INADDR_ANY) + && (ch->sg.grp.s_addr != INADDR_ANY)) + return; + + if ((ch->sg.src.s_addr == INADDR_ANY) + && (ch->sg.grp.s_addr == INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, + child)) { + if ((ch->sg.grp.s_addr != INADDR_ANY) + && (child->sg.grp.s_addr == ch->sg.grp.s_addr) + && (child != ch)) { + child->parent = ch; + listnode_add_sort(ch->sources, child); + } } - } } void pim_ifchannel_free(struct pim_ifchannel *ch) { - XFREE(MTYPE_PIM_IFCHANNEL, ch); + XFREE(MTYPE_PIM_IFCHANNEL, ch); } void pim_ifchannel_delete(struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp; - - pim_ifp = ch->interface->info; - - if (ch->upstream->channel_oil) - { - uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; - if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - mask = PIM_OIF_FLAG_PROTO_IGMP; - - /* SGRpt entry could have empty oil */ - if (ch->upstream->channel_oil) - pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask); - /* - * Do we have any S,G's that are inheriting? - * Nuke from on high too. - */ - if (ch->upstream->sources) - { - struct pim_upstream *child; - struct listnode *up_node; - - for (ALL_LIST_ELEMENTS_RO (ch->upstream->sources, up_node, child)) - pim_channel_del_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); + struct pim_interface *pim_ifp; + + pim_ifp = ch->interface->info; + + if (ch->upstream->channel_oil) { + uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + mask = PIM_OIF_FLAG_PROTO_IGMP; + + /* SGRpt entry could have empty oil */ + if (ch->upstream->channel_oil) + pim_channel_del_oif(ch->upstream->channel_oil, + ch->interface, mask); + /* + * Do we have any S,G's that are inheriting? + * Nuke from on high too. + */ + if (ch->upstream->sources) { + struct pim_upstream *child; + struct listnode *up_node; + + for (ALL_LIST_ELEMENTS_RO(ch->upstream->sources, + up_node, child)) + pim_channel_del_oif(child->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + } + } + + /* + * When this channel is removed + * we need to find all our children + * and make sure our pointers are fixed + */ + pim_ifchannel_remove_children(ch); + + if (ch->sources) + list_delete(ch->sources); + + listnode_delete(ch->upstream->ifchannels, ch); + + if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { + pim_upstream_update_join_desired(ch->upstream); } - } - - /* - * When this channel is removed - * we need to find all our children - * and make sure our pointers are fixed - */ - pim_ifchannel_remove_children (ch); - - if (ch->sources) - list_delete (ch->sources); - - listnode_delete(ch->upstream->ifchannels, ch); - - if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { - pim_upstream_update_join_desired(ch->upstream); - } - - /* upstream is common across ifchannels, check if upstream's - ifchannel list is empty before deleting upstream_del - ref count will take care of it. - */ - pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); - ch->upstream = NULL; - - THREAD_OFF(ch->t_ifjoin_expiry_timer); - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - THREAD_OFF(ch->t_ifassert_timer); - - if (ch->parent) - { - listnode_delete (ch->parent->sources, ch); - ch->parent = NULL; - } - /* - notice that listnode_delete() can't be moved - into pim_ifchannel_free() because the later is - called by list_delete_all_node() - */ - listnode_delete(pim_ifp->pim_ifchannel_list, ch); - hash_release(pim_ifp->pim_ifchannel_hash, ch); - listnode_delete(pim_ifchannel_list, ch); - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: ifchannel entry %s is deleted ", __PRETTY_FUNCTION__, ch->sg_str); - - pim_ifchannel_free(ch); + + /* upstream is common across ifchannels, check if upstream's + ifchannel list is empty before deleting upstream_del + ref count will take care of it. + */ + pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); + ch->upstream = NULL; + + THREAD_OFF(ch->t_ifjoin_expiry_timer); + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_OFF(ch->t_ifassert_timer); + + if (ch->parent) { + listnode_delete(ch->parent->sources, ch); + ch->parent = NULL; + } + /* + notice that listnode_delete() can't be moved + into pim_ifchannel_free() because the later is + called by list_delete_all_node() + */ + listnode_delete(pim_ifp->pim_ifchannel_list, ch); + hash_release(pim_ifp->pim_ifchannel_hash, ch); + listnode_delete(pim_ifchannel_list, ch); + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: ifchannel entry %s is deleted ", + __PRETTY_FUNCTION__, ch->sg_str); + + pim_ifchannel_free(ch); } -void -pim_ifchannel_delete_all (struct interface *ifp) +void pim_ifchannel_delete_all(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *ifchannel_node; - struct listnode *ifchannel_nextnode; - struct pim_ifchannel *ifchannel; - - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, ifchannel_node, - ifchannel_nextnode, ifchannel)) - { - pim_ifchannel_delete (ifchannel); - } + struct pim_interface *pim_ifp; + struct listnode *ifchannel_node; + struct listnode *ifchannel_nextnode; + struct pim_ifchannel *ifchannel; + + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, ifchannel_node, + ifchannel_nextnode, ifchannel)) { + pim_ifchannel_delete(ifchannel); + } } - + static void delete_on_noinfo(struct pim_ifchannel *ch) { - if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO && - ch->ifjoin_state == PIM_IFJOIN_NOINFO && - ch->t_ifjoin_expiry_timer == NULL) - pim_ifchannel_delete(ch); - + if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO + && ch->ifjoin_state == PIM_IFJOIN_NOINFO + && ch->t_ifjoin_expiry_timer == NULL) + pim_ifchannel_delete(ch); } -void pim_ifchannel_ifjoin_switch(const char *caller, - struct pim_ifchannel *ch, +void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, enum pim_ifjoin_state new_state) { - enum pim_ifjoin_state old_state = ch->ifjoin_state; - - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("PIM_IFCHANNEL(%s): %s is switching from %s to %s", - ch->interface->name, - ch->sg_str, - pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags), - pim_ifchannel_ifjoin_name (new_state, 0)); - - - if (old_state == new_state) { - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s calledby %s: non-transition on state %d (%s)", - __PRETTY_FUNCTION__, caller, new_state, - pim_ifchannel_ifjoin_name(new_state, 0)); - } - return; - } - - ch->ifjoin_state = new_state; - - if (ch->sg.src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = ch->upstream; - struct pim_upstream *child; - struct listnode *up_node; - - if (up) - { - if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) - { - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_interface *pim_ifp = ch->interface->info; - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Prune(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, up->sg_str); - if (!c_oil) - continue; - - if (!pim_upstream_evaluate_join_desired (child)) - { - pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_update_join_desired (child); - } - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - * I think this is dead code now. is it? - */ - if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); + enum pim_ifjoin_state old_state = ch->ifjoin_state; + + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "PIM_IFCHANNEL(%s): %s is switching from %s to %s", + ch->interface->name, ch->sg_str, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), + pim_ifchannel_ifjoin_name(new_state, 0)); + + + if (old_state == new_state) { + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug( + "%s calledby %s: non-transition on state %d (%s)", + __PRETTY_FUNCTION__, caller, new_state, + pim_ifchannel_ifjoin_name(new_state, 0)); } - } - if (ch->ifjoin_state == PIM_IFJOIN_JOIN) - { - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Join(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, up->sg_str); - - if (pim_upstream_evaluate_join_desired (child)) - { - pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_update_join_desired (child); - } + return; + } + + ch->ifjoin_state = new_state; + + if (ch->sg.src.s_addr == INADDR_ANY) { + struct pim_upstream *up = ch->upstream; + struct pim_upstream *child; + struct listnode *up_node; + + if (up) { + if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) { + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, + child)) { + struct channel_oil *c_oil = + child->channel_oil; + struct pim_interface *pim_ifp = + ch->interface->info; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: Prune(S,G)=%s from %s", + __FILE__, + __PRETTY_FUNCTION__, + child->sg_str, + up->sg_str); + if (!c_oil) + continue; + + if (!pim_upstream_evaluate_join_desired( + child)) { + pim_channel_del_oif( + c_oil, ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_update_join_desired( + child); + } + + /* + * If the S,G has no if channel and the + * c_oil still + * has output here then the *,G was + * supplying the implied + * if channel. So remove it. + * I think this is dead code now. is it? + */ + if (!ch + && c_oil->oil.mfcc_ttls + [pim_ifp->mroute_vif_index]) + pim_channel_del_oif( + c_oil, ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + } + } + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, + child)) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: Join(S,G)=%s from %s", + __FILE__, + __PRETTY_FUNCTION__, + child->sg_str, + up->sg_str); + + if (pim_upstream_evaluate_join_desired( + child)) { + pim_channel_add_oif( + child->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_update_join_desired( + child); + } + } + } } - } } - } - /* Transition to/from NOINFO ? */ - if ((old_state == PIM_IFJOIN_NOINFO) || - (new_state == PIM_IFJOIN_NOINFO)) { - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", - ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" : "UP"), - ch->sg_str, ch->interface->name); - } - - /* - Record uptime of state transition to/from NOINFO - */ - ch->ifjoin_creation = pim_time_monotonic_sec(); - - pim_upstream_update_join_desired(ch->upstream); - pim_ifchannel_update_could_assert(ch); - pim_ifchannel_update_assert_tracking_desired(ch); - } + /* Transition to/from NOINFO ? */ + if ((old_state == PIM_IFJOIN_NOINFO) + || (new_state == PIM_IFJOIN_NOINFO)) { + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", + ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" + : "UP"), + ch->sg_str, ch->interface->name); + } + + /* + Record uptime of state transition to/from NOINFO + */ + ch->ifjoin_creation = pim_time_monotonic_sec(); + + pim_upstream_update_join_desired(ch->upstream); + pim_ifchannel_update_could_assert(ch); + pim_ifchannel_update_assert_tracking_desired(ch); + } } const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, - int flags) + int flags) { - switch (ifjoin_state) { - case PIM_IFJOIN_NOINFO: - if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) - return "SGRpt"; - else - return "NOINFO"; - break; - case PIM_IFJOIN_JOIN: - return "JOIN"; - break; - case PIM_IFJOIN_PRUNE: - return "PRUNE"; - break; - case PIM_IFJOIN_PRUNE_PENDING: - return "PRUNEP"; - break; - case PIM_IFJOIN_PRUNE_TMP: - return "PRUNET"; - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - return "PRUNEPT"; - break; - } - - return "ifjoin_bad_state"; + switch (ifjoin_state) { + case PIM_IFJOIN_NOINFO: + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt"; + else + return "NOINFO"; + break; + case PIM_IFJOIN_JOIN: + return "JOIN"; + break; + case PIM_IFJOIN_PRUNE: + return "PRUNE"; + break; + case PIM_IFJOIN_PRUNE_PENDING: + return "PRUNEP"; + break; + case PIM_IFJOIN_PRUNE_TMP: + return "PRUNET"; + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + return "PRUNEPT"; + break; + } + + return "ifjoin_bad_state"; } const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state) { - switch (ifassert_state) { - case PIM_IFASSERT_NOINFO: return "NOINFO"; - case PIM_IFASSERT_I_AM_WINNER: return "WINNER"; - case PIM_IFASSERT_I_AM_LOSER: return "LOSER"; - } + switch (ifassert_state) { + case PIM_IFASSERT_NOINFO: + return "NOINFO"; + case PIM_IFASSERT_I_AM_WINNER: + return "WINNER"; + case PIM_IFASSERT_I_AM_LOSER: + return "LOSER"; + } - return "ifassert_bad_state"; + return "ifassert_bad_state"; } /* @@ -387,88 +402,85 @@ const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state) */ void reset_ifassert_state(struct pim_ifchannel *ch) { - struct in_addr any = { .s_addr = INADDR_ANY }; + struct in_addr any = {.s_addr = INADDR_ANY}; - THREAD_OFF(ch->t_ifassert_timer); + THREAD_OFF(ch->t_ifassert_timer); - pim_ifassert_winner_set(ch, - PIM_IFASSERT_NOINFO, - any, - qpim_infinite_assert_metric); + pim_ifassert_winner_set(ch, PIM_IFASSERT_NOINFO, any, + qpim_infinite_assert_metric); } struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, struct prefix_sg *sg) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_ifchannel lookup; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_ifchannel lookup; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), - ifp->name); - return NULL; - } + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); + return NULL; + } - lookup.sg = *sg; - ch = hash_lookup (pim_ifp->pim_ifchannel_hash, &lookup); + lookup.sg = *sg; + ch = hash_lookup(pim_ifp->pim_ifchannel_hash, &lookup); - return ch; + return ch; } static void ifmembership_set(struct pim_ifchannel *ch, enum pim_ifmembership membership) { - if (ch->local_ifmembership == membership) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, - membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" : "NOINFO", - ch->interface->name); - } - - ch->local_ifmembership = membership; - - pim_upstream_update_join_desired(ch->upstream); - pim_ifchannel_update_could_assert(ch); - pim_ifchannel_update_assert_tracking_desired(ch); + if (ch->local_ifmembership == membership) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" + : "NOINFO", + ch->interface->name); + } + + ch->local_ifmembership = membership; + + pim_upstream_update_join_desired(ch->upstream); + pim_ifchannel_update_could_assert(ch); + pim_ifchannel_update_assert_tracking_desired(ch); } void pim_ifchannel_membership_clear(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); + } } void pim_ifchannel_delete_on_noinfo(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - delete_on_noinfo(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + delete_on_noinfo(ch); + } } /* @@ -477,682 +489,687 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp) * If we are passed a *,G, find the *,* ifchannel * if we have it. */ -static struct pim_ifchannel * -pim_ifchannel_find_parent (struct pim_ifchannel *ch) +static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch) { - struct prefix_sg parent_sg = ch->sg; - struct pim_ifchannel *parent = NULL; - - // (S,G) - if ((parent_sg.src.s_addr != INADDR_ANY) && - (parent_sg.grp.s_addr != INADDR_ANY)) - { - parent_sg.src.s_addr = INADDR_ANY; - parent = pim_ifchannel_find (ch->interface, &parent_sg); - - if (parent) - listnode_add (parent->sources, ch); - return parent; - } - - return NULL; + struct prefix_sg parent_sg = ch->sg; + struct pim_ifchannel *parent = NULL; + + // (S,G) + if ((parent_sg.src.s_addr != INADDR_ANY) + && (parent_sg.grp.s_addr != INADDR_ANY)) { + parent_sg.src.s_addr = INADDR_ANY; + parent = pim_ifchannel_find(ch->interface, &parent_sg); + + if (parent) + listnode_add(parent->sources, ch); + return parent; + } + + return NULL; } -struct pim_ifchannel * -pim_ifchannel_add(struct interface *ifp, - struct prefix_sg *sg, int flags) +struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, + struct prefix_sg *sg, int flags) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_upstream *up; - - ch = pim_ifchannel_find(ifp, sg); - if (ch) - return ch; - - pim_ifp = ifp->info; - - up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); - if (!up) { - zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), ifp->name); - return NULL; - } - - ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); - if (!ch) { - zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", - __PRETTY_FUNCTION__, - up->sg_str, ifp->name); - - pim_upstream_del (up, __PRETTY_FUNCTION__); - return NULL; - } - - ch->flags = 0; - ch->upstream = up; - ch->interface = ifp; - ch->sg = *sg; - pim_str_sg_set (sg, ch->sg_str); - ch->parent = pim_ifchannel_find_parent (ch); - if (ch->sg.src.s_addr == INADDR_ANY) - { - ch->sources = list_new (); - ch->sources->cmp = (int (*)(void *, void *))pim_ifchannel_compare; - } - else - ch->sources = NULL; - - pim_ifchannel_find_new_children (ch); - ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; - - ch->ifjoin_state = PIM_IFJOIN_NOINFO; - ch->t_ifjoin_expiry_timer = NULL; - ch->t_ifjoin_prune_pending_timer = NULL; - ch->ifjoin_creation = 0; - - ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); - ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval (ch); - - ch->ifassert_winner.s_addr = 0; - - /* Assert state */ - ch->t_ifassert_timer = NULL; - ch->ifassert_state = PIM_IFASSERT_NOINFO; - reset_ifassert_state(ch); - if (pim_macro_ch_could_assert_eval(ch)) - PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); - else - PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - - if (pim_macro_assert_tracking_desired_eval(ch)) - PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); - else - PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - - /* Attach to list */ - listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); - ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); - listnode_add_sort(pim_ifchannel_list, ch); - - listnode_add_sort(up->ifchannels, ch); - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, ch->sg_str); - - return ch; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_upstream *up; + + ch = pim_ifchannel_find(ifp, sg); + if (ch) + return ch; + + pim_ifp = ifp->info; + + up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); + if (!up) { + zlog_err( + "%s: could not attach upstream (S,G)=%s on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); + return NULL; + } + + ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); + if (!ch) { + zlog_warn( + "%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", + __PRETTY_FUNCTION__, up->sg_str, ifp->name); + + pim_upstream_del(up, __PRETTY_FUNCTION__); + return NULL; + } + + ch->flags = 0; + ch->upstream = up; + ch->interface = ifp; + ch->sg = *sg; + pim_str_sg_set(sg, ch->sg_str); + ch->parent = pim_ifchannel_find_parent(ch); + if (ch->sg.src.s_addr == INADDR_ANY) { + ch->sources = list_new(); + ch->sources->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; + } else + ch->sources = NULL; + + pim_ifchannel_find_new_children(ch); + ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; + + ch->ifjoin_state = PIM_IFJOIN_NOINFO; + ch->t_ifjoin_expiry_timer = NULL; + ch->t_ifjoin_prune_pending_timer = NULL; + ch->ifjoin_creation = 0; + + ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); + ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch); + + ch->ifassert_winner.s_addr = 0; + + /* Assert state */ + ch->t_ifassert_timer = NULL; + ch->ifassert_state = PIM_IFASSERT_NOINFO; + reset_ifassert_state(ch); + if (pim_macro_ch_could_assert_eval(ch)) + PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); + else + PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + + if (pim_macro_assert_tracking_desired_eval(ch)) + PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); + else + PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + + /* Attach to list */ + listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); + ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); + listnode_add_sort(pim_ifchannel_list, ch); + + listnode_add_sort(up->ifchannels, ch); + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, + ch->sg_str); + + return ch; } static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del) { - pim_forward_stop(ch); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - if (ch_del) - delete_on_noinfo(ch); + pim_forward_stop(ch); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); + if (ch_del) + delete_on_noinfo(ch); } static int on_ifjoin_expiry_timer(struct thread *t) { - struct pim_ifchannel *ch; + struct pim_ifchannel *ch; - ch = THREAD_ARG(t); + ch = THREAD_ARG(t); - ifjoin_to_noinfo(ch, true); - /* ch may have been deleted */ + ifjoin_to_noinfo(ch, true); + /* ch may have been deleted */ - return 0; + return 0; } static int on_ifjoin_prune_pending_timer(struct thread *t) { - struct pim_ifchannel *ch; - int send_prune_echo; /* boolean */ - struct interface *ifp; - struct pim_interface *pim_ifp; - - ch = THREAD_ARG(t); - - if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) - { - /* Send PruneEcho(S,G) ? */ - ifp = ch->interface; - pim_ifp = ifp->info; - send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); - - if (send_prune_echo) - { - struct pim_rpf rpf; - - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; - pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); - } - /* If SGRpt flag is set on ifchannel, Trigger SGRpt - message on RP path upon prune timer expiry. - */ - if (PIM_IF_FLAG_TEST_S_G_RPT (ch->flags)) - { - if (ch->upstream) - pim_upstream_update_join_desired(ch->upstream); - /* - ch->ifjoin_state transition to NOINFO state - ch_del is set to 0 for not deleteing from here. - Holdtime expiry (ch_del set to 1) delete the entry. - */ - ifjoin_to_noinfo(ch, false); - } - else - ifjoin_to_noinfo(ch, true); - /* from here ch may have been deleted */ - } - else - { - zlog_warn("%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", - __PRETTY_FUNCTION__, pim_str_sg_dump (&ch->sg), - pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags)); - } - - return 0; + struct pim_ifchannel *ch; + int send_prune_echo; /* boolean */ + struct interface *ifp; + struct pim_interface *pim_ifp; + + ch = THREAD_ARG(t); + + if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { + /* Send PruneEcho(S,G) ? */ + ifp = ch->interface; + pim_ifp = ifp->info; + send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); + + if (send_prune_echo) { + struct pim_rpf rpf; + + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; + pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); + } + /* If SGRpt flag is set on ifchannel, Trigger SGRpt + message on RP path upon prune timer expiry. + */ + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) { + if (ch->upstream) + pim_upstream_update_join_desired(ch->upstream); + /* + ch->ifjoin_state transition to NOINFO state + ch_del is set to 0 for not deleteing from here. + Holdtime expiry (ch_del set to 1) delete the entry. + */ + ifjoin_to_noinfo(ch, false); + } else + ifjoin_to_noinfo(ch, true); + /* from here ch may have been deleted */ + } else { + zlog_warn( + "%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", + __PRETTY_FUNCTION__, pim_str_sg_dump(&ch->sg), + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); + } + + return 0; } -static void check_recv_upstream(int is_join, - struct interface *recv_ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - int holdtime) +static void check_recv_upstream(int is_join, struct interface *recv_ifp, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, int holdtime) { - struct pim_upstream *up; - - /* Upstream (S,G) in Joined state ? */ - up = pim_upstream_find(sg); - if (!up) - return; - if (up->join_state != PIM_UPSTREAM_JOINED) - return; - - /* Upstream (S,G) in Joined state */ - - if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { - /* RPF'(S,G) not found */ - zlog_warn("%s %s: RPF'%s not found", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str); - return; - } - - /* upstream directed to RPF'(S,G) ? */ - if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { - char up_str[INET_ADDRSTRLEN]; - char rpf_str[PREFIX_STRLEN]; - pim_inet4_dump("<up?>", upstream, up_str, sizeof(up_str)); - pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_warn("%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, - up_str, rpf_str, recv_ifp->name); - return; - } - /* upstream directed to RPF'(S,G) */ - - if (is_join) { - /* Join(S,G) to RPF'(S,G) */ - pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, holdtime); - return; - } - - /* Prune to RPF'(S,G) */ - - if (source_flags & PIM_RPT_BIT_MASK) { - if (source_flags & PIM_WILDCARD_BIT_MASK) { - /* Prune(*,G) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(*,G)", up); - return; - } - - /* Prune(S,G,rpt) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", up); - return; - } - - /* Prune(S,G) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up); + struct pim_upstream *up; + + /* Upstream (S,G) in Joined state ? */ + up = pim_upstream_find(sg); + if (!up) + return; + if (up->join_state != PIM_UPSTREAM_JOINED) + return; + + /* Upstream (S,G) in Joined state */ + + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { + /* RPF'(S,G) not found */ + zlog_warn("%s %s: RPF'%s not found", __FILE__, + __PRETTY_FUNCTION__, up->sg_str); + return; + } + + /* upstream directed to RPF'(S,G) ? */ + if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { + char up_str[INET_ADDRSTRLEN]; + char rpf_str[PREFIX_STRLEN]; + pim_inet4_dump("<up?>", upstream, up_str, sizeof(up_str)); + pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, + sizeof(rpf_str)); + zlog_warn( + "%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", + __FILE__, __PRETTY_FUNCTION__, up->sg_str, up_str, + rpf_str, recv_ifp->name); + return; + } + /* upstream directed to RPF'(S,G) */ + + if (is_join) { + /* Join(S,G) to RPF'(S,G) */ + pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, + holdtime); + return; + } + + /* Prune to RPF'(S,G) */ + + if (source_flags & PIM_RPT_BIT_MASK) { + if (source_flags & PIM_WILDCARD_BIT_MASK) { + /* Prune(*,G) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override( + "Prune(*,G)", up); + return; + } + + /* Prune(S,G,rpt) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", + up); + return; + } + + /* Prune(S,G) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up); } -static int -nonlocal_upstream(int is_join, - struct interface *recv_ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - uint16_t holdtime) +static int nonlocal_upstream(int is_join, struct interface *recv_ifp, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, uint16_t holdtime) { - struct pim_interface *recv_pim_ifp; - int is_local; /* boolean */ - - recv_pim_ifp = recv_ifp->info; - zassert(recv_pim_ifp); - - is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); - - if (is_local) - return 0; - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char up_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); - zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", - __PRETTY_FUNCTION__, - is_join ? "join" : "prune", - pim_str_sg_dump (sg), - up_str, recv_ifp->name); - } - - /* - * Since recv upstream addr was not directed to our primary - * address, check if we should react to it in any way. - */ - check_recv_upstream(is_join, recv_ifp, upstream, sg, - source_flags, holdtime); - - return 1; /* non-local */ + struct pim_interface *recv_pim_ifp; + int is_local; /* boolean */ + + recv_pim_ifp = recv_ifp->info; + zassert(recv_pim_ifp); + + is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); + + if (is_local) + return 0; + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char up_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); + zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", + __PRETTY_FUNCTION__, is_join ? "join" : "prune", + pim_str_sg_dump(sg), up_str, recv_ifp->name); + } + + /* + * Since recv upstream addr was not directed to our primary + * address, check if we should react to it in any way. + */ + check_recv_upstream(is_join, recv_ifp, upstream, sg, source_flags, + holdtime); + + return 1; /* non-local */ } -void pim_ifchannel_join_add(struct interface *ifp, - struct in_addr neigh_addr, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - uint16_t holdtime) +void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, uint16_t holdtime) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - - if (nonlocal_upstream(1 /* join */, ifp, upstream, - sg, source_flags, holdtime)) { - return; - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); - if (!ch) - return; - - /* - RFC 4601: 4.6.1. (S,G) Assert Message State Machine - - Transitions from "I am Assert Loser" State - - Receive Join(S,G) on Interface I - - We receive a Join(S,G) that has the Upstream Neighbor Address - field set to my primary IP address on interface I. The action is - to transition to NoInfo state, delete this (S,G) assert state - (Actions A5 below), and allow the normal PIM Join/Prune mechanisms - to operate. - - Notice: The nonlocal_upstream() test above ensures the upstream - address of the join message is our primary address. - */ - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - char neigh_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: Assert Loser recv Join%s from %s on %s", - __PRETTY_FUNCTION__, - ch->sg_str, neigh_str, ifp->name); - - assert_action_a5(ch); - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - - switch (ch->ifjoin_state) { - case PIM_IFJOIN_NOINFO: - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); - if (pim_macro_chisin_oiflist(ch)) { - pim_upstream_inherited_olist (ch->upstream); - pim_forward_start(ch); - } - /* - * If we are going to be a LHR, we need to note it - */ - if (ch->upstream->parent && - (ch->upstream->parent->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) && - !(ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) - { - pim_upstream_ref (ch->upstream, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); - pim_upstream_keep_alive_timer_start (ch->upstream, qpim_keep_alive_time); - } - break; - case PIM_IFJOIN_JOIN: - zassert(!ch->t_ifjoin_prune_pending_timer); - - /* - In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to a - previously received join message with holdtime=0xFFFF. - */ - if (ch->t_ifjoin_expiry_timer) { - unsigned long remain = - thread_timer_remain_second(ch->t_ifjoin_expiry_timer); - if (remain > holdtime) { + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + + if (nonlocal_upstream(1 /* join */, ifp, upstream, sg, source_flags, + holdtime)) { + return; + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); + if (!ch) + return; + /* - RFC 4601: 4.5.3. Receiving (S,G) Join/Prune Messages + RFC 4601: 4.6.1. (S,G) Assert Message State Machine + + Transitions from "I am Assert Loser" State - Transitions from Join State + Receive Join(S,G) on Interface I - The (S,G) downstream state machine on interface I remains in - Join state, and the Expiry Timer (ET) is restarted, set to - maximum of its current value and the HoldTime from the - triggering Join/Prune message. + We receive a Join(S,G) that has the Upstream Neighbor Address + field set to my primary IP address on interface I. The action is + to transition to NoInfo state, delete this (S,G) assert state + (Actions A5 below), and allow the normal PIM Join/Prune mechanisms + to operate. - Conclusion: Do not change the ET if the current value is - higher than the received join holdtime. + Notice: The nonlocal_upstream() test above ensures the upstream + address of the join message is our primary address. */ - return; - } - } - THREAD_OFF(ch->t_ifjoin_expiry_timer); - break; - case PIM_IFJOIN_PRUNE: - if (source_flags & PIM_ENCODE_RPT_BIT) - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - break; - case PIM_IFJOIN_PRUNE_PENDING: - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - if (source_flags & PIM_ENCODE_RPT_BIT) - { - THREAD_OFF(ch->t_ifjoin_expiry_timer); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - } - else - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); - break; - case PIM_IFJOIN_PRUNE_TMP: - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - break; - } - - if (holdtime != 0xFFFF) { - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + char neigh_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, + sizeof(neigh_str)); + zlog_warn("%s: Assert Loser recv Join%s from %s on %s", + __PRETTY_FUNCTION__, ch->sg_str, neigh_str, + ifp->name); + + assert_action_a5(ch); + } + + pim_ifp = ifp->info; + zassert(pim_ifp); + + switch (ch->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_JOIN); + if (pim_macro_chisin_oiflist(ch)) { + pim_upstream_inherited_olist(ch->upstream); + pim_forward_start(ch); + } + /* + * If we are going to be a LHR, we need to note it + */ + if (ch->upstream->parent && (ch->upstream->parent->flags + & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + && !(ch->upstream->flags + & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) { + pim_upstream_ref(ch->upstream, + PIM_UPSTREAM_FLAG_MASK_SRC_LHR, + __PRETTY_FUNCTION__); + pim_upstream_keep_alive_timer_start( + ch->upstream, qpim_keep_alive_time); + } + break; + case PIM_IFJOIN_JOIN: + zassert(!ch->t_ifjoin_prune_pending_timer); + + /* + In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to + a + previously received join message with holdtime=0xFFFF. + */ + if (ch->t_ifjoin_expiry_timer) { + unsigned long remain = thread_timer_remain_second( + ch->t_ifjoin_expiry_timer); + if (remain > holdtime) { + /* + RFC 4601: 4.5.3. Receiving (S,G) Join/Prune + Messages + + Transitions from Join State + + The (S,G) downstream state machine on + interface I remains in + Join state, and the Expiry Timer (ET) is + restarted, set to + maximum of its current value and the HoldTime + from the + triggering Join/Prune message. + + Conclusion: Do not change the ET if the + current value is + higher than the received join holdtime. + */ + return; + } + } + THREAD_OFF(ch->t_ifjoin_expiry_timer); + break; + case PIM_IFJOIN_PRUNE: + if (source_flags & PIM_ENCODE_RPT_BIT) + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_NOINFO); + break; + case PIM_IFJOIN_PRUNE_PENDING: + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + if (source_flags & PIM_ENCODE_RPT_BIT) { + THREAD_OFF(ch->t_ifjoin_expiry_timer); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_NOINFO); + } else + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_JOIN); + break; + case PIM_IFJOIN_PRUNE_TMP: + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + break; + } + + if (holdtime != 0xFFFF) { + thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, + &ch->t_ifjoin_expiry_timer); + } } -void pim_ifchannel_prune(struct interface *ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, +void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime) { - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; - int jp_override_interval_msec; - - if (nonlocal_upstream(0 /* prune */, ifp, upstream, - sg, source_flags, holdtime)) { - return; - } - - ch = pim_ifchannel_find (ifp, sg); - if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Received prune with no relevant ifchannel %s(%s) state: %d", - __PRETTY_FUNCTION__, ifp->name, pim_str_sg_dump (sg), source_flags); - return; - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); - if (!ch) - return; - - pim_ifp = ifp->info; - - switch (ch->ifjoin_state) { - case PIM_IFJOIN_NOINFO: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - if (!(source_flags & PIM_ENCODE_WC_BIT)) - PIM_IF_FLAG_SET_S_G_RPT(ch->flags); - - ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; - if (listcount(pim_ifp->pim_neighbor_list) > 1) - jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); - else - jp_override_interval_msec = 0; /* schedule to expire immediately */ - /* If we called ifjoin_prune() directly instead, care should - be taken not to use "ch" afterwards since it would be - deleted. */ + struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + int jp_override_interval_msec; - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, - jp_override_interval_msec, - &ch->t_ifjoin_prune_pending_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - pim_upstream_update_join_desired(ch->upstream); - } - break; - case PIM_IFJOIN_PRUNE_PENDING: - /* nothing to do */ - break; - case PIM_IFJOIN_JOIN: - THREAD_OFF(ch->t_ifjoin_expiry_timer); - - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_PRUNE_PENDING); - - if (listcount(pim_ifp->pim_neighbor_list) > 1) - jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); - else - jp_override_interval_msec = 0; /* schedule to expire immediately */ - /* If we called ifjoin_prune() directly instead, care should - be taken not to use "ch" afterwards since it would be - deleted. */ - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, - jp_override_interval_msec, - &ch->t_ifjoin_prune_pending_timer); - break; - case PIM_IFJOIN_PRUNE: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - case PIM_IFJOIN_PRUNE_TMP: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - ch->ifjoin_state = PIM_IFJOIN_PRUNE; - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - } + if (nonlocal_upstream(0 /* prune */, ifp, upstream, sg, source_flags, + holdtime)) { + return; + } + + ch = pim_ifchannel_find(ifp, sg); + if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Received prune with no relevant ifchannel %s(%s) state: %d", + __PRETTY_FUNCTION__, ifp->name, + pim_str_sg_dump(sg), source_flags); + return; + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); + if (!ch) + return; + + pim_ifp = ifp->info; + + switch (ch->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + if (source_flags & PIM_ENCODE_RPT_BIT) { + if (!(source_flags & PIM_ENCODE_WC_BIT)) + PIM_IF_FLAG_SET_S_G_RPT(ch->flags); + + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + if (listcount(pim_ifp->pim_neighbor_list) > 1) + jp_override_interval_msec = + pim_if_jp_override_interval_msec(ifp); + else + jp_override_interval_msec = + 0; /* schedule to expire immediately */ + /* If we called ifjoin_prune() directly instead, care + should + be taken not to use "ch" afterwards since it would be + deleted. */ + + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer_msec( + master, on_ifjoin_prune_pending_timer, ch, + jp_override_interval_msec, + &ch->t_ifjoin_prune_pending_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + pim_upstream_update_join_desired(ch->upstream); + } + break; + case PIM_IFJOIN_PRUNE_PENDING: + /* nothing to do */ + break; + case PIM_IFJOIN_JOIN: + THREAD_OFF(ch->t_ifjoin_expiry_timer); + + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_PRUNE_PENDING); + + if (listcount(pim_ifp->pim_neighbor_list) > 1) + jp_override_interval_msec = + pim_if_jp_override_interval_msec(ifp); + else + jp_override_interval_msec = + 0; /* schedule to expire immediately */ + /* If we called ifjoin_prune() directly instead, care should + be taken not to use "ch" afterwards since it would be + deleted. */ + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, + jp_override_interval_msec, + &ch->t_ifjoin_prune_pending_timer); + break; + case PIM_IFJOIN_PRUNE: + if (source_flags & PIM_ENCODE_RPT_BIT) { + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + case PIM_IFJOIN_PRUNE_TMP: + if (source_flags & PIM_ENCODE_RPT_BIT) { + ch->ifjoin_state = PIM_IFJOIN_PRUNE; + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + if (source_flags & PIM_ENCODE_RPT_BIT) { + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + } } -int -pim_ifchannel_local_membership_add(struct interface *ifp, - struct prefix_sg *sg) +int pim_ifchannel_local_membership_add(struct interface *ifp, + struct prefix_sg *sg) { - struct pim_ifchannel *ch, *starch; - struct pim_interface *pim_ifp; - - /* PIM enabled on interface? */ - pim_ifp = ifp->info; - if (!pim_ifp) - return 0; - if (!PIM_IF_TEST_PIM(pim_ifp->options)) - return 0; - - /* skip (*,G) ch creation if G is of type SSM */ - if (sg->src.s_addr == INADDR_ANY) - { - if (pim_is_grp_ssm (sg->grp)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug("%s: local membership (S,G)=%s ignored as group is SSM", - __PRETTY_FUNCTION__, pim_str_sg_dump (sg)); - return 1; - } - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); - if (!ch) { - return 0; - } - - ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); - - if (sg->src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = pim_upstream_find (sg); - struct pim_upstream *child; - struct listnode *up_node; - - starch = ch; - - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (PIM_DEBUG_EVENTS) - zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, ifp->name, up->sg_str); - - ch = pim_ifchannel_find (ifp, &child->sg); - if (pim_upstream_evaluate_join_desired_interface (child, ch, starch)) - { - pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_switch (child, PIM_UPSTREAM_JOINED); - } - } - - if (pimg->spt.switchover == PIM_SPT_INFINITY) - { - if (pimg->spt.plist) - { - struct prefix_list *plist = prefix_list_lookup (AFI_IP, pimg->spt.plist); - struct prefix g; - g.family = AF_INET; - g.prefixlen = IPV4_MAX_PREFIXLEN; - g.u.prefix4 = up->sg.grp; - - if (prefix_list_apply (plist, &g) == PREFIX_DENY) - { - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } - } - } - else - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } - - return 1; + struct pim_ifchannel *ch, *starch; + struct pim_interface *pim_ifp; + + /* PIM enabled on interface? */ + pim_ifp = ifp->info; + if (!pim_ifp) + return 0; + if (!PIM_IF_TEST_PIM(pim_ifp->options)) + return 0; + + /* skip (*,G) ch creation if G is of type SSM */ + if (sg->src.s_addr == INADDR_ANY) { + if (pim_is_grp_ssm(sg->grp)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "%s: local membership (S,G)=%s ignored as group is SSM", + __PRETTY_FUNCTION__, + pim_str_sg_dump(sg)); + return 1; + } + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); + if (!ch) { + return 0; + } + + ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); + + if (sg->src.s_addr == INADDR_ANY) { + struct pim_upstream *up = pim_upstream_find(sg); + struct pim_upstream *child; + struct listnode *up_node; + + starch = ch; + + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) { + if (PIM_DEBUG_EVENTS) + zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + child->sg_str, ifp->name, + up->sg_str); + + ch = pim_ifchannel_find(ifp, &child->sg); + if (pim_upstream_evaluate_join_desired_interface( + child, ch, starch)) { + pim_channel_add_oif(child->channel_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_switch(child, PIM_UPSTREAM_JOINED); + } + } + + if (pimg->spt.switchover == PIM_SPT_INFINITY) { + if (pimg->spt.plist) { + struct prefix_list *plist = prefix_list_lookup( + AFI_IP, pimg->spt.plist); + struct prefix g; + g.family = AF_INET; + g.prefixlen = IPV4_MAX_PREFIXLEN; + g.u.prefix4 = up->sg.grp; + + if (prefix_list_apply(plist, &g) + == PREFIX_DENY) { + pim_channel_add_oif( + up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } + } + } else + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } + + return 1; } void pim_ifchannel_local_membership_del(struct interface *ifp, struct prefix_sg *sg) { - struct pim_ifchannel *starch, *ch, *orig; - struct pim_interface *pim_ifp; - - /* PIM enabled on interface? */ - pim_ifp = ifp->info; - if (!pim_ifp) - return; - if (!PIM_IF_TEST_PIM(pim_ifp->options)) - return; - - orig = ch = pim_ifchannel_find(ifp, sg); - if (!ch) - return; - - ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); - - if (sg->src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = pim_upstream_find (sg); - struct pim_upstream *child; - struct listnode *up_node, *up_nnode; - - starch = ch; - - for (ALL_LIST_ELEMENTS (up->sources, up_node, up_nnode, child)) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg); - struct pim_interface *pim_ifp = ifp->info; - - if (PIM_DEBUG_EVENTS) - zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, ifp->name, child->sg_str); - - ch = pim_ifchannel_find (ifp, &child->sg); - if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch, starch)) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - */ - if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - - /* Child node removal/ref count-- will happen as part of parent' delete_no_info */ - } - } - delete_on_noinfo(orig); + struct pim_ifchannel *starch, *ch, *orig; + struct pim_interface *pim_ifp; + + /* PIM enabled on interface? */ + pim_ifp = ifp->info; + if (!pim_ifp) + return; + if (!PIM_IF_TEST_PIM(pim_ifp->options)) + return; + + orig = ch = pim_ifchannel_find(ifp, sg); + if (!ch) + return; + + ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); + + if (sg->src.s_addr == INADDR_ANY) { + struct pim_upstream *up = pim_upstream_find(sg); + struct pim_upstream *child; + struct listnode *up_node, *up_nnode; + + starch = ch; + + for (ALL_LIST_ELEMENTS(up->sources, up_node, up_nnode, child)) { + struct channel_oil *c_oil = child->channel_oil; + struct pim_ifchannel *chchannel = + pim_ifchannel_find(ifp, &child->sg); + struct pim_interface *pim_ifp = ifp->info; + + if (PIM_DEBUG_EVENTS) + zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + up->sg_str, ifp->name, + child->sg_str); + + ch = pim_ifchannel_find(ifp, &child->sg); + if (c_oil + && !pim_upstream_evaluate_join_desired_interface( + child, ch, starch)) + pim_channel_del_oif(c_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + + /* + * If the S,G has no if channel and the c_oil still + * has output here then the *,G was supplying the + * implied + * if channel. So remove it. + */ + if (!chchannel && c_oil + && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + pim_channel_del_oif(c_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + + /* Child node removal/ref count-- will happen as part of + * parent' delete_no_info */ + } + } + delete_on_noinfo(orig); } void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) { - int old_couldassert = PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)); - int new_couldassert = PIM_FORCE_BOOLEAN(pim_macro_ch_could_assert_eval(ch)); - - if (new_couldassert == old_couldassert) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - old_couldassert, new_couldassert); - } - - if (new_couldassert) { - /* CouldAssert(S,G,I) switched from FALSE to TRUE */ - PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); - } - else { - /* CouldAssert(S,G,I) switched from TRUE to FALSE */ - PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - - if (ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER) { - assert_action_a4(ch); - } - } - - pim_ifchannel_update_my_assert_metric(ch); + int old_couldassert = + PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)); + int new_couldassert = + PIM_FORCE_BOOLEAN(pim_macro_ch_could_assert_eval(ch)); + + if (new_couldassert == old_couldassert) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); + zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, old_couldassert, + new_couldassert); + } + + if (new_couldassert) { + /* CouldAssert(S,G,I) switched from FALSE to TRUE */ + PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); + } else { + /* CouldAssert(S,G,I) switched from TRUE to FALSE */ + PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + + if (ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER) { + assert_action_a4(ch); + } + } + + pim_ifchannel_update_my_assert_metric(ch); } /* @@ -1165,72 +1182,75 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) */ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch) { - struct pim_assert_metric my_metric_new = pim_macro_ch_my_assert_metric_eval(ch); - - if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric)) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char old_addr_str[INET_ADDRSTRLEN]; - char new_addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); - pim_inet4_dump("<old_addr?>", ch->ifassert_my_metric.ip_address, old_addr_str, sizeof(old_addr_str)); - pim_inet4_dump("<new_addr?>", my_metric_new.ip_address, new_addr_str, sizeof(new_addr_str)); - zlog_debug("%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - ch->ifassert_my_metric.rpt_bit_flag, - ch->ifassert_my_metric.metric_preference, - ch->ifassert_my_metric.route_metric, - old_addr_str, - my_metric_new.rpt_bit_flag, - my_metric_new.metric_preference, - my_metric_new.route_metric, - new_addr_str); - } - - ch->ifassert_my_metric = my_metric_new; - - if (pim_assert_metric_better(&ch->ifassert_my_metric, - &ch->ifassert_winner_metric)) { - assert_action_a5(ch); - } + struct pim_assert_metric my_metric_new = + pim_macro_ch_my_assert_metric_eval(ch); + + if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric)) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char old_addr_str[INET_ADDRSTRLEN]; + char new_addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("<old_addr?>", ch->ifassert_my_metric.ip_address, + old_addr_str, sizeof(old_addr_str)); + pim_inet4_dump("<new_addr?>", my_metric_new.ip_address, + new_addr_str, sizeof(new_addr_str)); + zlog_debug( + "%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, + ch->ifassert_my_metric.rpt_bit_flag, + ch->ifassert_my_metric.metric_preference, + ch->ifassert_my_metric.route_metric, old_addr_str, + my_metric_new.rpt_bit_flag, + my_metric_new.metric_preference, + my_metric_new.route_metric, new_addr_str); + } + + ch->ifassert_my_metric = my_metric_new; + + if (pim_assert_metric_better(&ch->ifassert_my_metric, + &ch->ifassert_winner_metric)) { + assert_action_a5(ch); + } } void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) { - int old_atd = PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)); - int new_atd = PIM_FORCE_BOOLEAN(pim_macro_assert_tracking_desired_eval(ch)); - - if (new_atd == old_atd) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - old_atd, new_atd); - } - - if (new_atd) { - /* AssertTrackingDesired(S,G,I) switched from FALSE to TRUE */ - PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); - } - else { - /* AssertTrackingDesired(S,G,I) switched from TRUE to FALSE */ - PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - assert_action_a5(ch); - } - } + int old_atd = PIM_FORCE_BOOLEAN( + PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)); + int new_atd = + PIM_FORCE_BOOLEAN(pim_macro_assert_tracking_desired_eval(ch)); + + if (new_atd == old_atd) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); + zlog_debug( + "%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, old_atd, new_atd); + } + + if (new_atd) { + /* AssertTrackingDesired(S,G,I) switched from FALSE to TRUE */ + PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); + } else { + /* AssertTrackingDesired(S,G,I) switched from TRUE to FALSE */ + PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + assert_action_a5(ch); + } + } } /* @@ -1239,36 +1259,34 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) * their upstream out that way and turn on forwarding * for that ifchannel then. */ -void -pim_ifchannel_scan_forward_start (struct interface *new_ifp) +void pim_ifchannel_scan_forward_start(struct interface *new_ifp) { - struct listnode *ifnode; - struct interface *ifp; - struct pim_interface *new_pim_ifp = new_ifp->info; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - { - struct pim_interface *loop_pim_ifp = ifp->info; - struct listnode *ch_node; - struct pim_ifchannel *ch; - - if (!loop_pim_ifp) - continue; - - if (new_pim_ifp == loop_pim_ifp) - continue; - - for (ALL_LIST_ELEMENTS_RO (loop_pim_ifp->pim_ifchannel_list, ch_node, ch)) - { - if (ch->ifjoin_state == PIM_IFJOIN_JOIN) - { - struct pim_upstream *up = ch->upstream; - if ((!up->channel_oil) && - (up->rpf.source_nexthop.interface == new_ifp)) - pim_forward_start (ch); - } - } - } + struct listnode *ifnode; + struct interface *ifp; + struct pim_interface *new_pim_ifp = new_ifp->info; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *loop_pim_ifp = ifp->info; + struct listnode *ch_node; + struct pim_ifchannel *ch; + + if (!loop_pim_ifp) + continue; + + if (new_pim_ifp == loop_pim_ifp) + continue; + + for (ALL_LIST_ELEMENTS_RO(loop_pim_ifp->pim_ifchannel_list, + ch_node, ch)) { + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { + struct pim_upstream *up = ch->upstream; + if ((!up->channel_oil) + && (up->rpf.source_nexthop + .interface == new_ifp)) + pim_forward_start(ch); + } + } + } } /* @@ -1278,87 +1296,89 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp) * reception of a *,G join as well, when * 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, uint8_t starg_alone) +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) { - struct pim_ifchannel *child; - struct listnode *ch_node; - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__, - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), - ch->sg_str, eom, join); - if (!ch->sources) - return; - - 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 (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)) - { - struct pim_upstream *up = child->upstream; - - PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); - if (up) - { - if (PIM_DEBUG_TRACE) - 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); - } - } - } - - if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) - continue; - - switch (child->ifjoin_state) - { - case PIM_IFJOIN_NOINFO: - case PIM_IFJOIN_JOIN: - break; - case PIM_IFJOIN_PRUNE: - if (!eom) - child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; - break; - case PIM_IFJOIN_PRUNE_PENDING: - if (!eom) - child->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING_TMP; - break; - case PIM_IFJOIN_PRUNE_TMP: - case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (eom) - child->ifjoin_state = PIM_IFJOIN_NOINFO; - break; + struct pim_ifchannel *child; + struct listnode *ch_node; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), + ch->sg_str, eom, join); + if (!ch->sources) + return; + + 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 (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)) { + struct pim_upstream *up = child->upstream; + + PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); + if (up) { + if (PIM_DEBUG_TRACE) + 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); + } + } + } + + if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) + continue; + + switch (child->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + case PIM_IFJOIN_JOIN: + break; + case PIM_IFJOIN_PRUNE: + if (!eom) + child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; + break; + case PIM_IFJOIN_PRUNE_PENDING: + if (!eom) + child->ifjoin_state = + PIM_IFJOIN_PRUNE_PENDING_TMP; + break; + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + if (eom) + child->ifjoin_state = PIM_IFJOIN_NOINFO; + break; + } } - } } -unsigned int -pim_ifchannel_hash_key (void *arg) +unsigned int pim_ifchannel_hash_key(void *arg) { - struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; + struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; - return jhash_2words (ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); + return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); } -int -pim_ifchannel_equal (const void *arg1, const void *arg2) +int pim_ifchannel_equal(const void *arg1, const void *arg2) { - const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1; - const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2; + const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1; + const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2; - if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) && - (ch1->sg.src.s_addr == ch2->sg.src.s_addr)) - return 1; + if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) + && (ch1->sg.src.s_addr == ch2->sg.src.s_addr)) + return 1; - return 0; + return 0; } |
