summaryrefslogtreecommitdiff
path: root/pimd/pim_zebra.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_zebra.c')
-rw-r--r--pimd/pim_zebra.c365
1 files changed, 196 insertions, 169 deletions
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 11ca6e8a10..70f099b0d7 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -150,6 +150,8 @@ static int pim_zebra_if_del(int command, struct zclient *zclient,
if (!if_is_operative(ifp))
pim_if_addr_del_all(ifp);
+ if_set_index(ifp, IFINDEX_INTERNAL);
+
return 0;
}
@@ -472,99 +474,84 @@ void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
struct pim_upstream *up,
struct pim_rpf *old)
{
- struct pim_neighbor *nbr;
+ if (old->source_nexthop.interface) {
+ struct pim_neighbor *nbr;
- nbr = pim_neighbor_find(old->source_nexthop.interface,
- old->rpf_addr.u.prefix4);
- if (nbr)
- pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
+ nbr = pim_neighbor_find(old->source_nexthop.interface,
+ old->rpf_addr.u.prefix4);
+ if (nbr)
+ pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
- /*
- * We have detected a case where we might need
- * to rescan the inherited o_list so do it.
- */
- if (up->channel_oil->oil_inherited_rescan) {
- pim_upstream_inherited_olist_decide(pim, up);
- up->channel_oil->oil_inherited_rescan = 0;
- }
-
- if (up->join_state == PIM_UPSTREAM_JOINED) {
/*
- * If we come up real fast we can be here
- * where the mroute has not been installed
- * so install it.
+ * We have detected a case where we might need
+ * to rescan the inherited o_list so do it.
*/
- if (!up->channel_oil->installed)
- pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
+ if (up->channel_oil->oil_inherited_rescan) {
+ pim_upstream_inherited_olist_decide(pim, up);
+ up->channel_oil->oil_inherited_rescan = 0;
+ }
+
+ if (up->join_state == PIM_UPSTREAM_JOINED) {
+ /*
+ * If we come up real fast we can be here
+ * where the mroute has not been installed
+ * so install it.
+ */
+ if (!up->channel_oil->installed)
+ pim_mroute_add(up->channel_oil,
+ __PRETTY_FUNCTION__);
+
+ /*
+ * RFC 4601: 4.5.7. Sending (S,G)
+ * Join/Prune Messages
+ *
+ * Transitions from Joined State
+ *
+ * RPF'(S,G) changes not due to an Assert
+ *
+ * The upstream (S,G) state machine remains
+ * in Joined state. Send Join(S,G) to the new
+ * upstream neighbor, which is the new value
+ * of RPF'(S,G). Send Prune(S,G) to the old
+ * upstream neighbor, which is the old value
+ * of RPF'(S,G). Set the Join Timer (JT) to
+ * expire after t_periodic seconds.
+ */
+ pim_jp_agg_switch_interface(old, &up->rpf, up);
+
+ pim_upstream_join_timer_restart(up, old);
+ } /* up->join_state == PIM_UPSTREAM_JOINED */
+ }
+ else {
/*
- * RFC 4601: 4.5.7. Sending (S,G)
- * Join/Prune Messages
- *
- * Transitions from Joined State
- *
- * RPF'(S,G) changes not due to an Assert
- *
- * The upstream (S,G) state machine remains
- * in Joined state. Send Join(S,G) to the new
- * upstream neighbor, which is the new value
- * of RPF'(S,G). Send Prune(S,G) to the old
- * upstream neighbor, which is the old value
- * of RPF'(S,G). Set the Join Timer (JT) to
- * expire after t_periodic seconds.
+ * We have detected a case where we might need
+ * to rescan the inherited o_list so do it.
*/
- pim_jp_agg_switch_interface(old, &up->rpf, up);
+ if (up->channel_oil->oil_inherited_rescan) {
+ pim_upstream_inherited_olist_decide(pim, up);
+ up->channel_oil->oil_inherited_rescan = 0;
+ }
- pim_upstream_join_timer_restart(up, old);
- } /* up->join_state == PIM_UPSTREAM_JOINED */
+ if (!up->channel_oil->installed)
+ pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
+ }
- /* FIXME can join_desired actually be changed by
- pim_rpf_update()
- returning PIM_RPF_CHANGED ? */
+ /* FIXME can join_desired actually be changed by pim_rpf_update()
+ * returning PIM_RPF_CHANGED ?
+ */
pim_upstream_update_join_desired(pim, up);
}
-static void scan_upstream_rpf_cache(struct pim_instance *pim)
-{
- struct listnode *up_node;
- struct listnode *up_nextnode;
- struct pim_upstream *up;
-
- for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
- enum pim_rpf_result rpf_result;
- struct pim_rpf old;
- struct prefix nht_p;
-
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
- pim_resolve_upstream_nh(pim, &nht_p);
-
- old.source_nexthop.interface = up->rpf.source_nexthop.interface;
- old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
- rpf_result = pim_rpf_update(pim, up, &old, 0);
-
- if (rpf_result == PIM_RPF_FAILURE)
- continue;
-
- if (rpf_result == PIM_RPF_CHANGED)
- pim_zebra_upstream_rpf_changed(pim, up, &old);
-
- } /* for (qpim_upstream_list) */
-
- pim_zebra_update_all_interfaces(pim);
-}
-
void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
{
struct in_addr vif_source;
int input_iface_vif_index;
int old_vif_index;
- if (!pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
+ pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
c_oil->oil.mfcc_origin,
- c_oil->oil.mfcc_mcastgrp))
- return;
+ c_oil->oil.mfcc_mcastgrp);
if (in_vif_index)
input_iface_vif_index = in_vif_index;
@@ -719,9 +706,6 @@ static int on_rpf_cache_refresh(struct thread *t)
{
struct pim_instance *pim = THREAD_ARG(t);
- /* update PIM protocol state */
- scan_upstream_rpf_cache(pim);
-
/* update kernel multicast forwarding cache (MFC) */
pim_scan_oil(pim);
@@ -950,112 +934,141 @@ void igmp_source_forward_start(struct pim_instance *pim,
struct pim_upstream *up = NULL;
if (!pim_rp_set_upstream_addr(pim, &vif_source,
- source->source_addr, sg.grp))
- return;
-
- /* Register addr with Zebra NHT */
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4 = vif_source;
- memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
+ source->source_addr, sg.grp)) {
+ /*Create a dummy channel oil */
+ source->source_channel_oil =
+ pim_channel_oil_add(pim, &sg, MAXVIFS);
- src.family = AF_INET;
- src.prefixlen = IPV4_MAX_BITLEN;
- src.u.prefix4 = vif_source; // RP or Src address
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = sg.grp;
+ if (!source->source_channel_oil) {
+ if (PIM_DEBUG_IGMP_TRACE) {
+ zlog_debug(
+ "%s %s: could not create OIL for channel (S,G)=%s",
+ __FILE__, __PRETTY_FUNCTION__,
+ pim_str_sg_dump(&sg));
+ }
+ return;
+ }
+ }
- if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
+ else {
+ /* Register addr with Zebra NHT */
+ nht_p.family = AF_INET;
+ nht_p.prefixlen = IPV4_MAX_BITLEN;
+ nht_p.u.prefix4 = vif_source;
+ memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
+
+ src.family = AF_INET;
+ src.prefixlen = IPV4_MAX_BITLEN;
+ src.u.prefix4 = vif_source; // RP or Src address
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = sg.grp;
+
+ if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
&out_pnc)) {
- if (out_pnc.nexthop_num) {
- up = pim_upstream_find(pim, &sg);
- memset(&nexthop, 0, sizeof(nexthop));
- if (up)
- memcpy(&nexthop,
- &up->rpf.source_nexthop,
- sizeof(struct pim_nexthop));
- pim_ecmp_nexthop_search(pim, &out_pnc, &nexthop,
- &src, &grp, 0);
- if (nexthop.interface)
- input_iface_vif_index =
+ if (out_pnc.nexthop_num) {
+ up = pim_upstream_find(pim, &sg);
+ memset(&nexthop, 0, sizeof(nexthop));
+ if (up)
+ memcpy(&nexthop,
+ &up->rpf.source_nexthop,
+ sizeof(struct pim_nexthop));
+ pim_ecmp_nexthop_search(pim, &out_pnc,
+ &nexthop,
+ &src, &grp, 0);
+ if (nexthop.interface)
+ input_iface_vif_index =
pim_if_find_vifindex_by_ifindex(
- pim,
- nexthop.interface->ifindex);
- } else {
- if (PIM_DEBUG_ZEBRA) {
- char buf1[INET_ADDRSTRLEN];
- char buf2[INET_ADDRSTRLEN];
- pim_inet4_dump("<source?>",
+ pim,
+ nexthop.interface->ifindex);
+ } else {
+ if (PIM_DEBUG_ZEBRA) {
+ char buf1[INET_ADDRSTRLEN];
+ char buf2[INET_ADDRSTRLEN];
+
+ pim_inet4_dump("<source?>",
nht_p.u.prefix4, buf1,
sizeof(buf1));
- pim_inet4_dump("<source?>",
+ pim_inet4_dump("<source?>",
grp.u.prefix4, buf2,
sizeof(buf2));
- zlog_debug(
+ zlog_debug(
"%s: NHT Nexthop not found for addr %s grp %s",
__PRETTY_FUNCTION__, buf1,
buf2);
+ }
}
- }
- } else
- input_iface_vif_index =
- pim_ecmp_fib_lookup_if_vif_index(pim, &src,
+ } else
+ input_iface_vif_index =
+ pim_ecmp_fib_lookup_if_vif_index(pim, &src,
&grp);
- if (PIM_DEBUG_ZEBRA) {
- char buf2[INET_ADDRSTRLEN];
- pim_inet4_dump("<source?>", vif_source, buf2,
- sizeof(buf2));
- zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
- __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
- buf2, input_iface_vif_index);
- }
-
- if (input_iface_vif_index < 1) {
- if (PIM_DEBUG_IGMP_TRACE) {
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<source?>", source->source_addr,
- source_str, sizeof(source_str));
- zlog_debug(
- "%s %s: could not find input interface for source %s",
- __FILE__, __PRETTY_FUNCTION__,
- source_str);
- }
- return;
- }
+ if (PIM_DEBUG_ZEBRA) {
+ char buf2[INET_ADDRSTRLEN];
- /*
- Protect IGMP against adding looped MFC entries created by both
- source and receiver attached to the same interface. See TODO
- T22.
- */
- if (input_iface_vif_index == pim_oif->mroute_vif_index) {
- /* ignore request for looped MFC entry */
- if (PIM_DEBUG_IGMP_TRACE) {
- zlog_debug(
- "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
+ pim_inet4_dump("<source?>", vif_source, buf2,
+ sizeof(buf2));
+ zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
__PRETTY_FUNCTION__,
pim_str_sg_dump(&sg),
- source->source_group->group_igmp_sock
- ->fd,
- source->source_group->group_igmp_sock
- ->interface->name,
- input_iface_vif_index);
+ buf2, input_iface_vif_index);
}
- return;
- }
- source->source_channel_oil =
- pim_channel_oil_add(pim, &sg, input_iface_vif_index);
- if (!source->source_channel_oil) {
- if (PIM_DEBUG_IGMP_TRACE) {
- zlog_debug(
- "%s %s: could not create OIL for channel (S,G)=%s",
- __FILE__, __PRETTY_FUNCTION__,
- pim_str_sg_dump(&sg));
+ if (input_iface_vif_index < 1) {
+ if (PIM_DEBUG_IGMP_TRACE) {
+ char source_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<source?>",
+ source->source_addr,
+ source_str, sizeof(source_str));
+ zlog_debug(
+ "%s %s: could not find input interface for source %s",
+ __FILE__, __PRETTY_FUNCTION__,
+ source_str);
+ }
+ source->source_channel_oil =
+ pim_channel_oil_add(pim, &sg, MAXVIFS);
+ }
+
+ else {
+ /*
+ * Protect IGMP against adding looped MFC
+ * entries created by both source and receiver
+ * attached to the same interface. See TODO
+ * T22.
+ */
+ if (input_iface_vif_index ==
+ pim_oif->mroute_vif_index) {
+ /* ignore request for looped MFC entry
+ */
+ if (PIM_DEBUG_IGMP_TRACE) {
+ zlog_debug(
+ "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
+ __PRETTY_FUNCTION__,
+ pim_str_sg_dump(&sg),
+ source->source_group
+ ->group_igmp_sock->fd,
+ source->source_group
+ ->group_igmp_sock
+ ->interface->name,
+ input_iface_vif_index);
+ }
+ return;
+ }
+
+ source->source_channel_oil =
+ pim_channel_oil_add(pim, &sg,
+ input_iface_vif_index);
+ if (!source->source_channel_oil) {
+ if (PIM_DEBUG_IGMP_TRACE) {
+ zlog_debug(
+ "%s %s: could not create OIL for channel (S,G)=%s",
+ __FILE__,
+ __PRETTY_FUNCTION__,
+ pim_str_sg_dump(&sg));
+ }
+ return;
+ }
}
- return;
}
}
@@ -1188,15 +1201,13 @@ void pim_forward_start(struct pim_ifchannel *ch)
sizeof(upstream_str));
zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
source_str, group_str, ch->interface->name,
- upstream_str);
+ inet_ntoa(up->upstream_addr));
}
/* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
as part of mroute_del called by pim_forward_stop.
*/
- if (!up->channel_oil
- || (up->channel_oil
- && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) {
+ if ((up->upstream_addr.s_addr != INADDR_ANY) && (!up->channel_oil)) {
struct prefix nht_p, src, grp;
struct pim_nexthop_cache out_pnc;
@@ -1267,17 +1278,33 @@ void pim_forward_start(struct pim_ifchannel *ch)
__FILE__, __PRETTY_FUNCTION__,
source_str);
}
- return;
+ up->channel_oil = pim_channel_oil_add(pim, &up->sg,
+ MAXVIFS);
}
+
+ else {
+ up->channel_oil = pim_channel_oil_add(pim, &up->sg,
+ input_iface_vif_index);
+ if (!up->channel_oil) {
+ if (PIM_DEBUG_PIM_TRACE)
+ zlog_debug(
+ "%s %s: could not create OIL for channel (S,G)=%s",
+ __FILE__, __PRETTY_FUNCTION__,
+ up->sg_str);
+ return;
+ }
+ }
+
if (PIM_DEBUG_TRACE) {
struct interface *in_intf = pim_if_find_by_vif_index(
pim, input_iface_vif_index);
zlog_debug(
"%s: Update channel_oil IIF %s VIFI %d entry %s ",
__PRETTY_FUNCTION__,
- in_intf ? in_intf->name : "NIL",
+ in_intf ? in_intf->name : "Unknown",
input_iface_vif_index, up->sg_str);
}
+
up->channel_oil = pim_channel_oil_add(pim, &up->sg,
input_iface_vif_index);
if (!up->channel_oil) {