}
up->sources = NULL;
+ list_delete (up->ifchannels);
+
/*
notice that listnode_delete() can't be moved
into pim_upstream_free() because the later is
{
char buf[PREFIX2STR_BUFFER];
prefix2str (&nht_p, buf, sizeof (buf));
- zlog_debug ("%s: Deregister upstream %s upstream addr %s with NHT ",
- __PRETTY_FUNCTION__, up->sg_str, buf);
+ zlog_debug ("%s: Deregister upstream %s addr %s with Zebra",
+ __PRETTY_FUNCTION__, up->sg_str, buf);
}
pim_delete_tracked_nexthop (&nht_p, up, NULL);
{
struct listnode *chnode;
struct listnode *chnextnode;
- struct pim_interface *pim_ifp;
- struct pim_ifchannel *ch;
+ struct pim_ifchannel *ch = NULL;
/* scan (S,G) state */
- for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
-
- if (ch->upstream != up)
- continue;
-
+ for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
if (pim_macro_chisin_oiflist(ch))
pim_forward_start(ch);
{
struct listnode *chnode;
struct listnode *chnextnode;
- struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
/* scan per-interface (S,G) state */
- for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
-
- if (ch->upstream != up)
- continue;
+ for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
pim_forward_stop(ch);
static int
pim_upstream_could_register (struct pim_upstream *up)
{
- struct pim_interface *pim_ifp = up->rpf.source_nexthop.interface->info;
+ struct pim_interface *pim_ifp = NULL;
+
+ if (up->rpf.source_nexthop.interface)
+ pim_ifp = up->rpf.source_nexthop.interface->info;
+ else
+ {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str);
+ }
if (pim_ifp && PIM_I_am_DR (pim_ifp) &&
pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src))
up->rpf.rpf_addr.family = AF_INET;
up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY;
+ up->ifchannels = list_new();
+ up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare;
+
if (up->sg.src.s_addr != INADDR_ANY)
wheel_add_item (pim_upstream_sg_wheel, up);
return NULL;
}
- pim_ifp = up->rpf.source_nexthop.interface->info;
- if (pim_ifp)
- up->channel_oil = pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index);
-
+ if (up->rpf.source_nexthop.interface)
+ {
+ pim_ifp = up->rpf.source_nexthop.interface->info;
+ if (pim_ifp)
+ up->channel_oil = pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index);
+ }
listnode_add_sort(pim_upstream_list, up);
if (PIM_DEBUG_TRACE)
if (PIM_DEBUG_TRACE)
{
if (up)
- zlog_debug("%s(%s): %s, found: %d: ref_count: %d",
+ {
+ char buf[PREFIX2STR_BUFFER];
+ prefix2str (&up->rpf.rpf_addr, buf, sizeof (buf));
+ zlog_debug("%s(%s): %s, iif %s found: %d: ref_count: %d",
__PRETTY_FUNCTION__, name,
- up->sg_str, found,
+ up->sg_str, buf, found,
up->ref_count);
+ }
else
zlog_debug("%s(%s): (%s) failure to create",
__PRETTY_FUNCTION__, name,
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 */
struct listnode *chnode;
struct listnode *chnextnode;
struct pim_ifchannel *ch;
- struct pim_interface *pim_ifp;
/* search all ifchannels */
- for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
-
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
-
- if (ch->upstream != up)
- continue;
-
+ for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) {
if (
/* RPF_interface(S) was NOT I */
{
struct listnode *chnode;
struct listnode *chnextnode;
- struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
/* scan per-interface (S,G) state */
- for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
-
- if (ch->upstream != up)
- continue;
-
+ for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
pim_ifchannel_update_could_assert(ch);
} /* scan iface channel list */
}
{
struct listnode *chnode;
struct listnode *chnextnode;
- struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
/* scan per-interface (S,G) state */
- for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
- pim_ifp = ch->interface->info;
- if (!pim_ifp)
- continue;
-
- if (ch->upstream != up)
- continue;
-
+ for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
pim_ifchannel_update_my_assert_metric(ch);
} /* scan iface channel list */
struct pim_ifchannel *ch;
/* scan per-interface (S,G) state */
- for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
+ for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
pim_ifp = ch->interface->info;
if (!pim_ifp)
continue;
- if (ch->upstream != up)
- continue;
-
pim_ifchannel_update_assert_tracking_desired(ch);
} /* scan iface channel list */
struct listnode *chnode;
struct pim_ifchannel *ch;
- for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch))
+ for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch))
{
- if ((ch->upstream == up) &&
- (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)))
- return 1;
+ if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
+ return 1;
}
return 0;
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 (up->rpf.source_nexthop.interface)
+ pim_ifp = up->rpf.source_nexthop.interface->info;
+ else
+ {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str);
+ }
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;
}
void
-pim_upstream_remove_lhr_star_pimreg (void)
+pim_upstream_spt_prefix_list_update (struct prefix_list *pl)
+{
+ const char *pname = prefix_list_name (pl);
+
+ if (pimg->spt.plist && strcmp (pimg->spt.plist, pname) == 0)
+ {
+ pim_upstream_remove_lhr_star_pimreg (pname);
+ }
+}
+
+/*
+ * nlist -> The new prefix list
+ *
+ * Per Group Application of pimreg to the OIL
+ * If the prefix list tells us DENY then
+ * we need to Switchover to SPT immediate
+ * so add the pimreg.
+ * If the prefix list tells us to ACCEPT than
+ * we need to Never do the SPT so remove
+ * the interface
+ *
+ */
+void
+pim_upstream_remove_lhr_star_pimreg (const char *nlist)
{
struct pim_upstream *up;
struct listnode *node;
+ struct prefix_list *np;
+ struct prefix g;
+ enum prefix_list_type apply_new;
+
+ np = prefix_list_lookup (AFI_IP, nlist);
+
+ g.family = AF_INET;
+ g.prefixlen = IPV4_MAX_PREFIXLEN;
for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up))
{
if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))
continue;
- pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+ if (!nlist)
+ {
+ pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+ continue;
+ }
+ g.u.prefix4 = up->sg.grp;
+ apply_new = prefix_list_apply (np, &g);
+ if (apply_new == PREFIX_DENY)
+ pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+ else
+ pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
}
}