summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-09-13 19:43:39 -0400
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-09-13 19:43:39 -0400
commit37736d087067cda2bc6a6371cc20e42f5cd92cdd (patch)
tree6f49808475b1af27a74d740ffa6ab515d005ac97
parent7577536c5c2dfb78f7af01cdb6d980023efccb18 (diff)
pimd: More S,G RPT prune state missinformation
If you read the extra fine print of the PIM RFC it asks you to stop the PP Timer and the Expiry Timer when you are certain S,G RPT states. This commit puts this into practice and it also deletes the S,G ifchannel if necessary. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com.
-rw-r--r--pimd/pim_ifchannel.c56
1 files changed, 31 insertions, 25 deletions
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index b5d6f04948..e0d2c78fe4 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -1327,7 +1327,7 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
uint8_t join)
{
struct pim_ifchannel *child;
- struct listnode *ch_node;
+ struct listnode *ch_node, *nch_node;
struct pim_instance *pim =
((struct pim_interface *)ch->interface->info)->pim;
@@ -1339,7 +1339,7 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
if (!ch->sources)
return;
- for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) {
+ for (ALL_LIST_ELEMENTS(ch->sources, ch_node, nch_node, child)) {
if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
continue;
@@ -1358,30 +1358,36 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
break;
case PIM_IFJOIN_PRUNE_TMP:
case PIM_IFJOIN_PRUNE_PENDING_TMP:
- if (eom) {
- struct pim_upstream *parent =
- child->upstream->parent;
-
- PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
- child->ifjoin_state = PIM_IFJOIN_NOINFO;
-
- if (I_am_RP(pim, child->sg.grp)) {
- pim_channel_add_oif(
- child->upstream->channel_oil,
- ch->interface,
- PIM_OIF_FLAG_PROTO_STAR);
- pim_upstream_switch(
- pim, child->upstream,
- PIM_UPSTREAM_JOINED);
- pim_jp_agg_single_upstream_send(
- &child->upstream->rpf,
- child->upstream, true);
- }
- if (parent)
- pim_jp_agg_single_upstream_send(
- &parent->rpf,
- parent, true);
+ if (!eom)
+ break;
+
+ if (child->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING_TMP)
+ THREAD_OFF(child->t_ifjoin_prune_pending_timer);
+ THREAD_OFF(child->t_ifjoin_expiry_timer);
+ struct pim_upstream *parent =
+ child->upstream->parent;
+
+ PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
+ child->ifjoin_state = PIM_IFJOIN_NOINFO;
+
+ if (I_am_RP(pim, child->sg.grp)) {
+ pim_channel_add_oif(
+ child->upstream->channel_oil,
+ ch->interface,
+ PIM_OIF_FLAG_PROTO_STAR);
+ pim_upstream_switch(
+ pim, child->upstream,
+ PIM_UPSTREAM_JOINED);
+ pim_jp_agg_single_upstream_send(
+ &child->upstream->rpf,
+ child->upstream, true);
}
+ if (parent)
+ pim_jp_agg_single_upstream_send(
+ &parent->rpf,
+ parent, true);
+
+ delete_on_noinfo(child);
break;
}
}