summaryrefslogtreecommitdiff
path: root/pimd/pim_ifchannel.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-06-22 11:05:03 -0400
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-07-24 13:51:40 -0400
commit0885a9f1f4352996d95766b69fc29e464adee01c (patch)
tree93cca0199ebd05321ecc31928f5c43eed9a6f89a /pimd/pim_ifchannel.c
parent96ceedc7a27404a148bc9cc513b5b60e286cffc2 (diff)
pimd: Fix code to not send joins when SGRPT Prune is received
When we receive a SGRPT Prune we were switching the upstream to JOINED and immediately sending a join. This was not the right thing to do. This was happening because we were making decisions about the new ifchannel before it was fully formed. Rework ifchannel startup to provide enough information to the pim upstream data structure to make the right decisions Ticket: CM-16425 Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'pimd/pim_ifchannel.c')
-rw-r--r--pimd/pim_ifchannel.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 5f3901e49b..922ee647a5 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -509,7 +509,8 @@ static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch)
}
struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
- struct prefix_sg *sg, int flags)
+ struct prefix_sg *sg,
+ uint8_t source_flags, int up_flags)
{
struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
@@ -521,27 +522,19 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
pim_ifp = ifp->info;
- up = pim_upstream_add(pim_ifp->pim, 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(pim_ifp->pim, up, __PRETTY_FUNCTION__);
return NULL;
}
ch->flags = 0;
- ch->upstream = up;
+ if ((source_flags & PIM_ENCODE_RPT_BIT)
+ && !(source_flags & PIM_ENCODE_WC_BIT))
+ PIM_IF_FLAG_SET_S_G_RPT(ch->flags);
+
ch->interface = ifp;
ch->sg = *sg;
pim_str_sg_set(sg, ch->sg_str);
@@ -561,6 +554,32 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
ch->t_ifjoin_prune_pending_timer = NULL;
ch->ifjoin_creation = 0;
+ /* 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_ifp->pim->ifchannel_list, ch);
+
+ up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags,
+ __PRETTY_FUNCTION__, ch);
+
+ if (!up) {
+ zlog_err(
+ "%s: could not attach upstream (S,G)=%s on interface %s",
+ __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
+
+ pim_ifchannel_remove_children(ch);
+ if (ch)
+ list_delete(ch->sources);
+
+ listnode_delete(pim_ifp->pim_ifchannel_list, ch);
+ hash_release(pim_ifp->pim_ifchannel_hash, ch);
+ listnode_delete(pim_ifp->pim->ifchannel_list, ch);
+ XFREE(MTYPE_PIM_IFCHANNEL, ch);
+ return NULL;
+ }
+
+ listnode_add_sort(up->ifchannels, ch);
+
ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch);
ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch);
@@ -580,13 +599,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
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_ifp->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);
@@ -772,7 +784,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
return;
}
- ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
+ ch = pim_ifchannel_add(ifp, sg, source_flags,
+ PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
if (!ch)
return;
@@ -914,7 +927,8 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
return;
}
- ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
+ ch = pim_ifchannel_add(ifp, sg, source_flags,
+ PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
if (!ch)
return;
@@ -1027,7 +1041,7 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
}
}
- ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
+ ch = pim_ifchannel_add(ifp, sg, 0, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
if (!ch) {
return 0;
}