pim_ifchannel_local_membership_add(struct interface *ifp,
struct prefix_sg *sg)
{
- struct pim_ifchannel *ch;
+ struct pim_ifchannel *ch, *starch;
struct pim_interface *pim_ifp;
/* PIM enabled on interface? */
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);
+ 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);
- if (pim_upstream_evaluate_join_desired_interface (child, ch))
- {
- pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
- pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
- }
+ 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)
void pim_ifchannel_local_membership_del(struct interface *ifp,
struct prefix_sg *sg)
{
- struct pim_ifchannel *ch;
+ struct pim_ifchannel *starch, *ch, *orig;
struct pim_interface *pim_ifp;
/* PIM enabled on interface? */
if (!PIM_IF_TEST_PIM(pim_ifp->options))
return;
- ch = pim_ifchannel_find(ifp, sg);
+ orig = ch = pim_ifchannel_find(ifp, sg);
if (!ch)
return;
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;
__FILE__, __PRETTY_FUNCTION__,
up->sg_str, ifp->name, child->sg_str);
- if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch))
+ 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);
/*
pim_upstream_del (child, __PRETTY_FUNCTION__);
}
}
- delete_on_noinfo(ch);
+ delete_on_noinfo(orig);
}
void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch)
return up;
}
+/*
+ * Passed in up must be the upstream for ch. starch is NULL if no
+ * information
+ */
int
pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,
- struct pim_ifchannel *ch)
+ struct pim_ifchannel *ch,
+ struct pim_ifchannel *starch)
{
- struct pim_upstream *parent = up->parent;
-
- if (ch->upstream == up)
+ if (ch)
{
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
- return 0;
+ return 0;
if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch))
- return 1;
+ return 1;
}
/*
* joins (*,G)
*/
- if (parent && ch->upstream == parent)
+ if (starch)
{
- struct listnode *ch_node;
- struct pim_ifchannel *child;
- for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child))
- {
- if (child->upstream == up)
- {
- if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
- return 0;
- }
- }
- if (!pim_macro_ch_lost_assert (ch) && pim_macro_chisin_joins_or_include (ch))
- return 1;
+ if (PIM_IF_FLAG_TEST_S_G_RPT (starch->upstream->flags))
+ return 0;
+
+ if (!pim_macro_ch_lost_assert (starch) && pim_macro_chisin_joins_or_include (starch))
+ return 1;
}
return 0;
*/
int pim_upstream_evaluate_join_desired(struct pim_upstream *up)
{
- struct listnode *chnode;
- struct listnode *chnextnode;
- struct pim_interface *pim_ifp;
- struct pim_ifchannel *ch;
+ struct interface *ifp;
+ struct listnode *node;
+ struct pim_ifchannel *ch, *starch;
+ struct pim_upstream *starup = up->parent;
int ret = 0;
- /* scan per-interface (S,G) state */
- for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch))
+ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
{
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
+ if (!ifp->info)
+ continue;
+
+ ch = pim_ifchannel_find (ifp, &up->sg);
+
+ if (starup)
+ starch = pim_ifchannel_find (ifp, &starup->sg);
+ else
+ starch = NULL;
- ret += pim_upstream_evaluate_join_desired_interface (up, ch);
+ if (!ch && !starch)
+ continue;
+
+ ret += pim_upstream_evaluate_join_desired_interface (up, ch, starch);
} /* scan iface channel list */
return ret; /* false */
int
pim_upstream_inherited_olist_decide (struct pim_upstream *up)
{
- struct pim_interface *pim_ifp;
- struct listnode *chnextnode;
- struct pim_ifchannel *ch;
- struct listnode *chnode;
+ struct interface *ifp;
+ struct pim_interface *pim_ifp = NULL;
+ struct pim_ifchannel *ch, *starch;
+ struct listnode *node;
+ struct pim_upstream *starup = up->parent;
int output_intf = 0;
pim_ifp = up->rpf.source_nexthop.interface->info;
if (pim_ifp && !up->channel_oil)
up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index);
- for (ALL_LIST_ELEMENTS (pim_ifchannel_list, chnode, chnextnode, ch))
+ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
{
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
+ if (!ifp->info)
+ continue;
- if (pim_upstream_evaluate_join_desired_interface (up, ch))
- {
+ ch = pim_ifchannel_find (ifp, &up->sg);
+
+ if (starup)
+ starch = pim_ifchannel_find (ifp, &starup->sg);
+ else
+ starch = NULL;
+
+ if (!ch && !starch)
+ continue;
+
+ if (pim_upstream_evaluate_join_desired_interface (up, ch, starch))
+ {
int flag = PIM_OIF_FLAG_PROTO_PIM;
- if (ch->sg.src.s_addr == INADDR_ANY && ch->upstream != up)
+ if (!ch)
flag = PIM_OIF_FLAG_PROTO_STAR;
- pim_channel_add_oif (up->channel_oil, ch->interface, flag);
- output_intf++;
- }
+
+ pim_channel_add_oif (up->channel_oil, ifp, flag);
+ output_intf++;
+ }
}
return output_intf;