summaryrefslogtreecommitdiff
path: root/pimd/pim_ifchannel.c
diff options
context:
space:
mode:
authorwhitespace / reindent <invalid@invalid.invalid>2017-07-17 14:03:14 +0200
committerwhitespace / reindent <invalid@invalid.invalid>2017-07-17 14:04:07 +0200
commitd62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch)
tree3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /pimd/pim_ifchannel.c
parent888ac268a0077fc9ebd1218cec6ae472af0bfc40 (diff)
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.c2254
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;
}