summaryrefslogtreecommitdiff
path: root/pimd
diff options
context:
space:
mode:
Diffstat (limited to 'pimd')
-rw-r--r--pimd/pim_cmd.c155
-rw-r--r--pimd/pim_ifchannel.c2
-rw-r--r--pimd/pim_igmp_mtrace.c7
-rw-r--r--pimd/pim_join.c6
-rw-r--r--pimd/pim_jp_agg.c14
-rw-r--r--pimd/pim_mroute.c16
-rw-r--r--pimd/pim_nht.c57
-rw-r--r--pimd/pim_nht.h1
-rw-r--r--pimd/pim_oil.c58
-rw-r--r--pimd/pim_oil.h20
-rw-r--r--pimd/pim_register.c12
-rw-r--r--pimd/pim_rp.c202
-rw-r--r--pimd/pim_rp.h8
-rw-r--r--pimd/pim_rpf.c33
-rw-r--r--pimd/pim_rpf.h3
-rw-r--r--pimd/pim_upstream.c189
-rw-r--r--pimd/pim_upstream.h24
-rw-r--r--pimd/pim_zebra.c365
-rw-r--r--pimd/pim_zlookup.c2
-rw-r--r--pimd/pimd.c4
20 files changed, 780 insertions, 398 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index f521704f1b..70b3ae10e5 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -198,7 +198,7 @@ static void pim_show_assert_helper(struct vty *vty,
pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation);
pim_time_timer_to_mmss(timer, sizeof(timer), ch->t_ifassert_timer);
- vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
+ vty_out(vty, "%-16s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
pim_ifchannel_ifassert_name(ch->ifassert_state), winner_str,
uptime, timer);
@@ -214,7 +214,7 @@ static void pim_show_assert(struct pim_instance *pim, struct vty *vty)
now = pim_time_monotonic_sec();
vty_out(vty,
- "Interface Address Source Group State Winner Uptime Timer\n");
+ "Interface Address Source Group State Winner Uptime Timer\n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
@@ -239,7 +239,7 @@ static void pim_show_assert_internal_helper(struct vty *vty,
pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
- vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
+ vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
@@ -261,7 +261,7 @@ static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty)
"eATD: Evaluate AssertTrackingDesired\n\n");
vty_out(vty,
- "Interface Address Source Group CA eCA ATD eATD\n");
+ "Interface Address Source Group CA eCA ATD eATD\n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
if (!pim_ifp)
@@ -292,7 +292,7 @@ static void pim_show_assert_metric_helper(struct vty *vty,
pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
pim_inet4_dump("<addr?>", am.ip_address, addr_str, sizeof(addr_str));
- vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
+ vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
am.rpt_bit_flag ? "yes" : "no", am.metric_preference,
am.route_metric, addr_str);
@@ -305,7 +305,7 @@ static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty)
struct interface *ifp;
vty_out(vty,
- "Interface Address Source Group RPT Pref Metric Address \n");
+ "Interface Address Source Group RPT Pref Metric Address \n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
@@ -349,7 +349,7 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
else
snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric);
- vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
+ vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
am->rpt_bit_flag ? "yes" : "no", pref_str, metr_str, addr_str);
}
@@ -362,7 +362,7 @@ static void pim_show_assert_winner_metric(struct pim_instance *pim,
struct interface *ifp;
vty_out(vty,
- "Interface Address Source Group RPT Pref Metric Address \n");
+ "Interface Address Source Group RPT Pref Metric Address \n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
@@ -462,7 +462,7 @@ static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
json, JSON_C_TO_STRING_PRETTY));
} else {
vty_out(vty,
- "Interface Address Source Group Membership\n");
+ "Interface Address Source Group Membership\n");
/*
* Example of the json data we are traversing
@@ -499,7 +499,7 @@ static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
type = json_object_get_type(if_field_val);
if (type == json_type_object) {
- vty_out(vty, "%-9s ", key);
+ vty_out(vty, "%-16s ", key);
json_object_object_get_ex(
val, "address", &json_tmp);
@@ -566,7 +566,7 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
json = json_object_new_object();
else
vty_out(vty,
- "Interface State Address V Querier Query Timer Uptime\n");
+ "Interface State Address V Querier Query Timer Uptime\n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
struct pim_interface *pim_ifp;
@@ -614,7 +614,7 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
}
} else {
vty_out(vty,
- "%-9s %5s %15s %d %7s %11s %8s\n",
+ "%-16s %5s %15s %d %7s %11s %8s\n",
ifp->name,
if_is_up(ifp)
? (igmp->mtrace_only ? "mtrc"
@@ -854,7 +854,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
now = pim_time_monotonic_sec();
vty_out(vty,
- "Interface Address Source Group Socket Uptime \n");
+ "Interface Address Source Group Socket Uptime \n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
struct pim_interface *pim_ifp;
@@ -888,7 +888,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
pim_inet4_dump("<src?>", ij->source_addr, source_str,
sizeof(source_str));
- vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s\n",
+ vty_out(vty, "%-16s %-15s %-15s %-15s %6d %8s\n",
ifp->name, pri_addr_str, source_str, group_str,
ij->sock_fd, uptime);
} /* for (pim_ifp->igmp_join_list) */
@@ -1191,7 +1191,7 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
vty_out(vty, "Designated Router\n");
vty_out(vty, "-----------------\n");
vty_out(vty, "Address : %s\n", dr_str);
- vty_out(vty, "Priority : %d(%d)\n",
+ vty_out(vty, "Priority : %u(%d)\n",
pim_ifp->pim_dr_priority,
pim_ifp->pim_dr_num_nondrpri_neighbors);
vty_out(vty, "Uptime : %s\n", dr_uptime);
@@ -1421,11 +1421,11 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
json, JSON_C_TO_STRING_PRETTY));
} else {
vty_out(vty,
- "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
+ "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
json_object_object_foreach(json, key, val)
{
- vty_out(vty, "%-9s ", key);
+ vty_out(vty, "%-16s ", key);
json_object_object_get_ex(val, "state", &json_tmp);
vty_out(vty, "%5s ", json_object_get_string(json_tmp));
@@ -1474,12 +1474,13 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
json = json_object_new_object();
else {
vty_out(vty, "\n");
- vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
- "Interface", " HELLO", " JOIN", " PRUNE",
- " REGISTER", " REGISTER-STOP", " ASSERT");
- vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
- " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
- " Rx/Tx", " Rx/Tx");
+ vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+ "Interface", " HELLO", " JOIN",
+ " PRUNE", " REGISTER", "REGISTER-STOP",
+ " ASSERT");
+ vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
+ " Rx/Tx", " Rx/Tx", " Rx/Tx",
+ " Rx/Tx", " Rx/Tx", " Rx/Tx");
vty_out(vty,
"---------------------------------------------------------------------------------------------------------------\n");
}
@@ -1519,7 +1520,7 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
json_object_object_add(json, ifp->name, json_row);
} else {
vty_out(vty,
- "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
+ "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
ifp->name, pim_ifp->pim_ifstat_hello_recv,
pim_ifp->pim_ifstat_hello_sent,
pim_ifp->pim_ifstat_join_recv,
@@ -1555,14 +1556,14 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
json = json_object_new_object();
else {
vty_out(vty, "\n");
- vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+ vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n",
"Interface", " HELLO", " JOIN", " PRUNE",
" REGISTER", " REGISTER-STOP", " ASSERT");
- vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
+ vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
" Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
" Rx/Tx", " Rx/Tx");
vty_out(vty,
- "---------------------------------------------------------------------------------------------------------------\n");
+ "---------------------------------------------------------------------------------------------------------------------\n");
}
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -1605,7 +1606,7 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
json_object_object_add(json, ifp->name, json_row);
} else {
vty_out(vty,
- "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
+ "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
ifp->name, pim_ifp->pim_ifstat_hello_recv,
pim_ifp->pim_ifstat_hello_sent,
pim_ifp->pim_ifstat_join_recv,
@@ -1687,7 +1688,7 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
} else
json_object_object_add(json_grp, ch_src_str, json_row);
} else {
- vty_out(vty, "%-9s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
+ vty_out(vty, "%-16s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
ch_grp_str,
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
@@ -1709,7 +1710,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, bool uj)
json = json_object_new_object();
else
vty_out(vty,
- "Interface Address Source Group State Uptime Expire Prune\n");
+ "Interface Address Source Group State Uptime Expire Prune\n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
@@ -1957,7 +1958,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
vty_out(vty,
"Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)");
vty_out(vty,
- "\nInstalled Source Group IIF OIL\n");
+ "\nInstalled Source Group IIF OIL\n");
}
for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
@@ -2040,9 +2041,8 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
c_oil->cc.wrong_if);
}
} else {
- vty_out(vty, "%-9d %-15s %-15s %-7s ",
- c_oil->installed, src_str, grp_str,
- in_ifname);
+ vty_out(vty, "%-9d %-15s %-15s %-16s ",
+ c_oil->installed, src_str, grp_str, in_ifname);
}
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
@@ -2159,7 +2159,7 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
json = json_object_new_object();
} else {
vty_out(vty,
- "Interface Neighbor Uptime Holdtime DR Pri\n");
+ "Interface Neighbor Uptime Holdtime DR Pri\n");
}
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2201,7 +2201,7 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
neigh_src_str, json_row);
} else {
- vty_out(vty, "%-9s %15s %8s %8s %6d\n",
+ vty_out(vty, "%-16s %15s %8s %8s %6d\n",
ifp->name, neigh_src_str, uptime,
expire, neigh->dr_priority);
}
@@ -2226,7 +2226,7 @@ static void pim_show_neighbors_secondary(struct pim_instance *pim,
struct interface *ifp;
vty_out(vty,
- "Interface Address Neighbor Secondary \n");
+ "Interface Address Neighbor Secondary \n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
struct pim_interface *pim_ifp;
@@ -2263,7 +2263,7 @@ static void pim_show_neighbors_secondary(struct pim_instance *pim,
prefix2str(p, neigh_sec_str,
sizeof(neigh_sec_str));
- vty_out(vty, "%-9s %-15s %-15s %-15s\n",
+ vty_out(vty, "%-16s %-15s %-15s %-15s\n",
ifp->name, inet_ntoa(ifaddr),
neigh_src_str, neigh_sec_str);
}
@@ -2350,7 +2350,7 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
json = json_object_new_object();
else
vty_out(vty,
- "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n");
+ "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n");
for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
char src_str[INET_ADDRSTRLEN];
@@ -2370,9 +2370,10 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
up->t_join_timer);
/*
- * If we have a J/P timer for the neighbor display that
+ * If the upstream is not dummy and it has a J/P timer for the
+ * neighbor display that
*/
- if (!up->t_join_timer) {
+ if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
struct pim_neighbor *nbr;
nbr = pim_neighbor_find(
@@ -2412,8 +2413,10 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
json_row = json_object_new_object();
json_object_pim_upstream_add(json_row, up);
json_object_string_add(
- json_row, "inboundInterface",
- up->rpf.source_nexthop.interface->name);
+ json_row, "inboundInterface",
+ up->rpf.source_nexthop.interface
+ ? up->rpf.source_nexthop.interface->name
+ : "Unknown");
/*
* The RPF address we use is slightly different
@@ -2462,9 +2465,11 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
json_object_object_add(json_group, src_str, json_row);
} else {
vty_out(vty,
- "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
- up->rpf.source_nexthop.interface->name, src_str,
- grp_str, state_str, uptime, join_timer,
+ "%-16s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
+ up->rpf.source_nexthop.interface
+ ? up->rpf.source_nexthop.interface->name
+ : "Unknown",
+ src_str, grp_str, state_str, uptime, join_timer,
rs_timer, ka_timer, up->ref_count);
}
}
@@ -2522,7 +2527,7 @@ static void pim_show_join_desired_helper(struct pim_instance *pim,
json_object_object_add(json_group, src_str, json_row);
} else {
- vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
+ vty_out(vty, "%-16s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
ch->interface->name, src_str, grp_str,
pim_macro_ch_lost_assert(ch) ? "yes" : "no",
pim_macro_chisin_joins(ch) ? "yes" : "no",
@@ -2548,7 +2553,7 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
json = json_object_new_object();
else
vty_out(vty,
- "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
+ "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
/* scan per-interface (S,G) state */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2584,7 +2589,7 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
json = json_object_new_object();
else
vty_out(vty,
- "Source Group RpfIface RibNextHop RpfAddress \n");
+ "Source Group RpfIface RibNextHop RpfAddress \n");
for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
char src_str[INET_ADDRSTRLEN];
@@ -2627,7 +2632,7 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
rpf_addr_str);
json_object_object_add(json_group, src_str, json_row);
} else {
- vty_out(vty, "%-15s %-15s %-8s %-15s %-15s\n", src_str,
+ vty_out(vty, "%-15s %-15s %-16s %-15s %-15s\n", src_str,
grp_str, rpf_ifname, rpf_nexthop_str,
rpf_addr_str);
}
@@ -2721,7 +2726,7 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
show_rpf_refresh_stats(vty, pim, now, json);
vty_out(vty, "\n");
vty_out(vty,
- "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
+ "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
}
for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) {
@@ -2769,7 +2774,7 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
json_object_object_add(json_group, src_str, json_row);
} else {
- vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n",
+ vty_out(vty, "%-15s %-15s %-16s %-15s %-15s %6d %4d\n",
src_str, grp_str, rpf_ifname, rpf_addr_str,
rib_nexthop_str,
rpf->source_nexthop.mrib_route_metric,
@@ -2804,7 +2809,7 @@ static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
vty_out(vty, "%-15s ", inet_ntoa(pnc->rpf.rpf_addr.u.prefix4));
- vty_out(vty, "%-14s ", ifp ? ifp->name : "NULL");
+ vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
vty_out(vty, "%s ", inet_ntoa(nh_node->gate.ipv4));
vty_out(vty, "\n");
}
@@ -2819,8 +2824,8 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
cwd.pim = pim;
vty_out(vty, "Number of registered addresses: %lu\n",
pim->rpf_hash->count);
- vty_out(vty, "Address Interface Nexthop\n");
- vty_out(vty, "-------------------------------------------\n");
+ vty_out(vty, "Address Interface Nexthop\n");
+ vty_out(vty, "---------------------------------------------\n");
hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
}
@@ -2839,7 +2844,7 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
json = json_object_new_object();
else
vty_out(vty,
- "Interface Address Group Mode Timer Srcs V Uptime \n");
+ "Interface Address Group Mode Timer Srcs V Uptime \n");
/* scan interfaces */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2919,7 +2924,7 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
} else {
vty_out(vty,
- "%-9s %-15s %-15s %4s %8s %4d %d %8s\n",
+ "%-16s %-15s %-15s %4s %8s %4d %d %8s\n",
ifp->name, ifaddr_str,
group_str,
grp->igmp_version == 3
@@ -2951,7 +2956,7 @@ static void igmp_show_group_retransmission(struct pim_instance *pim,
struct interface *ifp;
vty_out(vty,
- "Interface Address Group RetTimer Counter RetSrcs\n");
+ "Interface Address Group RetTimer Counter RetSrcs\n");
/* scan interfaces */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2999,7 +3004,7 @@ static void igmp_show_group_retransmission(struct pim_instance *pim,
}
}
- vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d\n",
+ vty_out(vty, "%-16s %-15s %-15s %-8s %7d %7d\n",
ifp->name, ifaddr_str, group_str,
grp_retr_mmss,
grp->group_specific_query_retransmit_count,
@@ -3018,7 +3023,7 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
now = pim_time_monotonic_sec();
vty_out(vty,
- "Interface Address Group Source Timer Fwd Uptime \n");
+ "Interface Address Group Source Timer Fwd Uptime \n");
/* scan interfaces */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3070,7 +3075,7 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
now - src->source_creation);
vty_out(vty,
- "%-9s %-15s %-15s %-15s %5s %3s %8s\n",
+ "%-16s %-15s %-15s %-15s %5s %3s %8s\n",
ifp->name, ifaddr_str,
group_str, source_str, mmss,
IGMP_SOURCE_TEST_FORWARDING(
@@ -3091,7 +3096,7 @@ static void igmp_show_source_retransmission(struct pim_instance *pim,
struct interface *ifp;
vty_out(vty,
- "Interface Address Group Source Counter\n");
+ "Interface Address Group Source Counter\n");
/* scan interfaces */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3133,7 +3138,7 @@ static void igmp_show_source_retransmission(struct pim_instance *pim,
source_str, sizeof(source_str));
vty_out(vty,
- "%-9s %-15s %-15s %-15s %7d\n",
+ "%-16s %-15s %-15s %-15s %7d\n",
ifp->name, ifaddr_str,
group_str, source_str,
src->source_query_retransmit_count);
@@ -4373,7 +4378,7 @@ static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
vty_out(vty, "\n");
vty_out(vty,
- "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
+ "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
FOR_ALL_INTERFACES (pim->vrf, ifp) {
struct pim_interface *pim_ifp;
@@ -4398,7 +4403,7 @@ static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
ifaddr = pim_ifp->primary_address;
- vty_out(vty, "%-12s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
+ vty_out(vty, "%-16s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
ifp->name, inet_ntoa(ifaddr), ifp->ifindex,
pim_ifp->mroute_vif_index, (unsigned long)vreq.icount,
(unsigned long)vreq.ocount, (unsigned long)vreq.ibytes,
@@ -4527,7 +4532,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
json = json_object_new_object();
} else {
vty_out(vty,
- "Source Group Proto Input Output TTL Uptime\n");
+ "Source Group Proto Input Output TTL Uptime\n");
}
now = pim_time_monotonic_sec();
@@ -4589,7 +4594,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
++oif_vif_index) {
struct interface *ifp_out;
- char oif_uptime[10];
+ char mroute_uptime[10];
int ttl;
ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
@@ -4598,8 +4603,8 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
pim_time_uptime(
- oif_uptime, sizeof(oif_uptime),
- now - c_oil->oif_creation[oif_vif_index]);
+ mroute_uptime, sizeof(mroute_uptime),
+ now - c_oil->mroute_creation);
found_oif = 1;
if (ifp_out)
@@ -4647,7 +4652,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
oif_vif_index);
json_object_int_add(json_ifp_out, "ttl", ttl);
json_object_string_add(json_ifp_out, "upTime",
- oif_uptime);
+ mroute_uptime);
if (!json_oil) {
json_oil = json_object_new_object();
json_object_object_add(json_source,
@@ -4677,9 +4682,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
}
vty_out(vty,
- "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n",
+ "%-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
src_str, grp_str, proto, in_ifname,
- out_ifname, ttl, oif_uptime);
+ out_ifname, ttl, mroute_uptime);
if (first) {
src_str[0] = '\0';
@@ -4691,7 +4696,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
}
if (!uj && !found_oif) {
- vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n",
+ vty_out(vty, "%-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
src_str, grp_str, "none", in_ifname, "none", 0,
"--:--:--");
}
@@ -4798,7 +4803,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
json_ifp_out);
} else {
vty_out(vty,
- "%-15s %-15s %-6s %-10s %-10s %-3d %8s %s\n",
+ "%-15s %-15s %-6s %-16s %-16s %-3d %8s %s\n",
src_str, grp_str, proto, in_ifname,
out_ifname, ttl, oif_uptime,
pim->vrf->name);
@@ -4813,7 +4818,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
if (!uj && !found_oif) {
vty_out(vty,
- "%-15s %-15s %-6s %-10s %-10s %-3d %8s %s\n",
+ "%-15s %-15s %-6s %-16s %-16s %-3d %8s %s\n",
src_str, grp_str, proto, in_ifname, "none", 0,
"--:--:--", pim->vrf->name);
}
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 14ce8d7d9f..0fe4110f60 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -911,7 +911,7 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) {
if (PIM_DEBUG_TRACE)
zlog_debug(
- "%s: Received prune with no relevant ifchannel %s(%s) state: %d",
+ "%s: Received prune with no relevant ifchannel %s%s state: %d",
__PRETTY_FUNCTION__, ifp->name,
pim_str_sg_dump(sg), source_flags);
return;
diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c
index 1fb624a6a0..f51e0c0d2f 100644
--- a/pimd/pim_igmp_mtrace.c
+++ b/pimd/pim_igmp_mtrace.c
@@ -133,6 +133,13 @@ static bool mtrace_fwd_info(struct pim_instance *pim,
if (!up)
return false;
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: up %s RPF is not present",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return false;
+ }
+
ifp_in = up->rpf.source_nexthop.interface;
nh_addr = up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4;
total = htonl(MTRACE_UNKNOWN_COUNT);
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index ae5032be73..cbacaf3ea8 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -439,9 +439,6 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
size_t packet_size = 0;
size_t group_size = 0;
- on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface,
- rpf->rpf_addr.u.prefix4);
-
if (rpf->source_nexthop.interface)
pim_ifp = rpf->source_nexthop.interface->info;
else {
@@ -450,6 +447,9 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
return -1;
}
+ on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface,
+ rpf->rpf_addr.u.prefix4);
+
if (!pim_ifp) {
zlog_warn("%s: multicast not enabled on interface %s",
__PRETTY_FUNCTION__,
diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c
index 7726ffda57..06a9e6d0d6 100644
--- a/pimd/pim_jp_agg.c
+++ b/pimd/pim_jp_agg.c
@@ -213,8 +213,18 @@ void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore)
{
#ifdef PIM_JP_AGG_DEBUG
struct interface *ifp;
- struct pim_interface *pim_ifp = up->rpf.source_nexthop.interface->info;
- struct pim_instance *pim = pim_ifp->pim;
+ struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
+
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: up %s RPF is not present",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return;
+ }
+
+ pim_ifp = up->rpf.source_nexthop.interface->info;
+ pim = pim_ifp->pim;
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index dd9e21cae8..999a1eb580 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -234,7 +234,8 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
up->channel_oil->cc.pktcnt++;
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
// resolve mfcc_parent prior to mroute_add in channel_add_oif
- if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) {
+ if (up->rpf.source_nexthop.interface &&
+ up->channel_oil->oil.mfcc_parent >= MAXVIFS) {
int vif_index = 0;
vif_index = pim_if_find_vifindex_by_ifindex(
pim_ifp->pim,
@@ -301,6 +302,13 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
return 0;
}
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: up %s RPF is not present",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return 0;
+ }
+
pim_ifp = up->rpf.source_nexthop.interface->info;
rpg = pim_ifp ? RP(pim_ifp->pim, sg.grp) : NULL;
@@ -956,6 +964,8 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
}
c_oil->installed = 1;
+ c_oil->mroute_creation = pim_time_monotonic_sec();
+
return 0;
}
@@ -1022,7 +1032,7 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
sg.grp = c_oil->oil.mfcc_mcastgrp;
if (PIM_DEBUG_MROUTE)
zlog_debug(
- "Channel(%s) is not installed no need to collect data from kernel",
+ "Channel%s is not installed no need to collect data from kernel",
pim_str_sg_dump(&sg));
}
return;
@@ -1041,7 +1051,7 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
sg.grp = c_oil->oil.mfcc_mcastgrp;
zlog_warn(
- "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s",
+ "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=%s: errno=%d: %s",
(unsigned long)SIOCGETSGCNT,
pim_str_sg_dump(&sg), errno,
safe_strerror(errno));
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index b6cd1a7d11..9b5379384c 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -39,6 +39,7 @@
#include "pim_jp_agg.h"
#include "pim_zebra.h"
#include "pim_zlookup.h"
+#include "pim_rp.h"
/**
* pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
@@ -170,6 +171,8 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
struct pim_nexthop_cache *pnc = NULL;
struct pim_nexthop_cache lookup;
struct zclient *zclient = NULL;
+ struct listnode *upnode = NULL;
+ struct pim_upstream *upstream = NULL;
zclient = pim_zebra_zclient_get();
@@ -177,8 +180,30 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
lookup.rpf.rpf_addr = *addr;
pnc = hash_lookup(pim->rpf_hash, &lookup);
if (pnc) {
- if (rp)
+ if (rp) {
+ /* Release the (*, G)upstream from pnc->upstream_hash,
+ * whose Group belongs to the RP getting deleted
+ */
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
+ upstream)) {
+ struct prefix grp;
+ struct rp_info *trp_info;
+
+ if (upstream->sg.src.s_addr != INADDR_ANY)
+ continue;
+
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = upstream->sg.grp;
+
+ trp_info = pim_rp_find_match_group(pim, &grp);
+ if (trp_info == rp)
+ hash_release(pnc->upstream_hash,
+ upstream);
+ }
listnode_delete(pnc->rp_list, rp);
+ }
+
if (up)
hash_release(pnc->upstream_hash, up);
@@ -207,6 +232,17 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
}
}
+void pim_rp_nexthop_del(struct rp_info *rp_info)
+{
+ rp_info->rp.source_nexthop.interface = NULL;
+ rp_info->rp.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr =
+ PIM_NET_INADDR_ANY;
+ rp_info->rp.source_nexthop.mrib_metric_preference =
+ router->infinite_assert_metric.metric_preference;
+ rp_info->rp.source_nexthop.mrib_route_metric =
+ router->infinite_assert_metric.route_metric;
+}
+
/* Update RP nexthop info based on Nexthop update received from Zebra.*/
static void pim_update_rp_nh(struct pim_instance *pim,
struct pim_nexthop_cache *pnc)
@@ -220,9 +256,11 @@ static void pim_update_rp_nh(struct pim_instance *pim,
continue;
// Compute PIM RPF using cached nexthop
- pim_ecmp_nexthop_search(pim, pnc, &rp_info->rp.source_nexthop,
- &rp_info->rp.rpf_addr, &rp_info->group,
- 1);
+ if (!pim_ecmp_nexthop_search(pim, pnc,
+ &rp_info->rp.source_nexthop,
+ &rp_info->rp.rpf_addr, &rp_info->group,
+ 1))
+ pim_rp_nexthop_del(rp_info);
}
}
@@ -278,12 +316,12 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
old.source_nexthop.interface = up->rpf.source_nexthop.interface;
rpf_result = pim_rpf_update(pim, up, &old, 0);
if (rpf_result == PIM_RPF_FAILURE) {
- pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
+ pim_upstream_rpf_clear(pim, up);
return HASHWALK_CONTINUE;
}
/* update kernel multicast forwarding cache (MFC) */
- if (up->channel_oil) {
+ if (up->rpf.source_nexthop.interface) {
ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex;
vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex);
@@ -306,9 +344,10 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
if (PIM_DEBUG_PIM_NHT) {
zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s",
- __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
- old.source_nexthop.interface->name,
- up->rpf.source_nexthop.interface->name);
+ __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
+ old.source_nexthop.interface
+ ? old.source_nexthop.interface->name : "Unknwon",
+ up->rpf.source_nexthop.interface->name);
}
return HASHWALK_CONTINUE;
diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h
index 796fbf9731..6eff7bbc89 100644
--- a/pimd/pim_nht.h
+++ b/pimd/pim_nht.h
@@ -68,4 +68,5 @@ void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
void pim_resolve_upstream_nh(struct pim_instance *pim, struct prefix *nht_p);
int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim,
struct prefix *src, struct prefix *grp);
+void pim_rp_nexthop_del(struct rp_info *rp_info);
#endif
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c
index 2e12d728cf..55d26113f7 100644
--- a/pimd/pim_oil.c
+++ b/pimd/pim_oil.c
@@ -168,13 +168,15 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
return c_oil;
}
- ifp = pim_if_find_by_vif_index(pim, input_vif_index);
- if (!ifp) {
- /* warning only */
- zlog_warn(
- "%s: (S,G)=%s could not find input interface for input_vif_index=%d",
- __PRETTY_FUNCTION__, pim_str_sg_dump(sg),
- input_vif_index);
+ if (input_vif_index != MAXVIFS) {
+ ifp = pim_if_find_by_vif_index(pim, input_vif_index);
+ if (!ifp) {
+ /* warning only */
+ zlog_warn(
+ "%s: (S,G)=%s could not find input interface for input_vif_index=%d",
+ __PRETTY_FUNCTION__, pim_str_sg_dump(sg),
+ input_vif_index);
+ }
}
c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil));
@@ -447,25 +449,31 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] =
PIM_MROUTE_MIN_TTL;
- if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) {
- if (PIM_DEBUG_MROUTE) {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<group?>",
- channel_oil->oil.mfcc_mcastgrp,
- group_str, sizeof(group_str));
- pim_inet4_dump("<source?>",
- channel_oil->oil.mfcc_origin, source_str,
- sizeof(source_str));
- zlog_debug(
- "%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__, oif->name,
- pim_ifp->mroute_vif_index, source_str,
- group_str);
- }
+ /* channel_oil->oil.mfcc_parent != MAXVIFS indicate this entry is not
+ * valid to get installed in kernel.
+ */
+ if (channel_oil->oil.mfcc_parent != MAXVIFS) {
+ if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) {
+ if (PIM_DEBUG_MROUTE) {
+ char group_str[INET_ADDRSTRLEN];
+ char source_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<group?>",
+ channel_oil->oil.mfcc_mcastgrp,
+ group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>",
+ channel_oil->oil.mfcc_origin, source_str,
+ sizeof(source_str));
+ zlog_debug(
+ "%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
+ __FILE__, __PRETTY_FUNCTION__, oif->name,
+ pim_ifp->mroute_vif_index, source_str,
+ group_str);
+ }
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
- return -5;
+ channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]
+ = old_ttl;
+ return -5;
+ }
}
channel_oil->oif_creation[pim_ifp->mroute_vif_index] =
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index 94d3840e98..8b95324142 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -64,6 +64,25 @@ struct channel_counts {
Each channel_oil.oil is used to control an (S,G) entry in the Kernel
Multicast Forwarding Cache.
+
+ There is a case when we create a channel_oil but don't install in the kernel
+
+ Case where (S, G) entry not installed in the kernel:
+ FRR receives IGMP/PIM (*, G) join and RP is not configured or
+ not-reachable, then create a channel_oil for the group G with the incoming
+ interface(channel_oil.oil.mfcc_parent) as invalid i.e "MAXVIF" and populate
+ the outgoing interface where join is received. Keep this entry in the stack,
+ but don't install in the kernel(channel_oil.installed = 0).
+
+ Case where (S, G) entry installed in the kernel:
+ When RP is configured and is reachable for the group G, and receiving a
+ join if channel_oil is already present then populate the incoming interface
+ and install the entry in the kernel, if channel_oil not present, then create
+ a new_channel oil(channel_oil.installed = 1).
+
+ is_valid: indicate if this entry is valid to get installed in kernel.
+ installed: indicate if this entry is installed in the kernel.
+
*/
struct channel_oil {
@@ -78,6 +97,7 @@ struct channel_oil {
uint32_t oif_flags[MAXVIFS];
struct channel_counts cc;
struct pim_upstream *up;
+ time_t mroute_creation;
};
extern struct list *pim_channel_oil_list;
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index 4b402de634..386ed1d424 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -97,7 +97,7 @@ void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg,
pinfo = (struct pim_interface *)ifp->info;
if (!pinfo) {
if (PIM_DEBUG_PIM_TRACE)
- zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__);
+ zlog_debug("%s: No pinfo!", __PRETTY_FUNCTION__);
return;
}
if (pim_msg_send(pinfo->pim_sock_fd, src, originator, buffer,
@@ -279,14 +279,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
- if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, ip_hdr->ip_dst,
- dest_addr)) {
+ if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, dest_addr)) {
if (PIM_DEBUG_PIM_REG) {
char dest[INET_ADDRSTRLEN];
pim_inet4_dump("<dst?>", dest_addr, dest, sizeof(dest));
zlog_debug(
- "%s: Received Register message for %s that I do not own",
+ "%s: Received Register message for destination address: %s that I do not own",
__func__, dest);
}
return 0;
@@ -330,9 +329,8 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_debug(
- "Received Register message(%s) from %s on %s, rp: %d",
- pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp);
+ zlog_debug("Received Register message%s from %s on %s, rp: %d",
+ pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp);
}
if (i_am_rp
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 308d5a5e06..b7db7d0418 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -45,7 +45,9 @@
#include "pim_iface.h"
#include "pim_msdp.h"
#include "pim_nht.h"
-
+#include "pim_mroute.h"
+#include "pim_oil.h"
+#include "pim_zebra.h"
/* Cleanup pim->rpf_hash each node data */
void pim_rp_list_hash_clean(void *data)
@@ -200,7 +202,7 @@ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim,
/*
* Given a group, return the rp_info for that group
*/
-static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
+struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
const struct prefix *group)
{
struct listnode *node;
@@ -333,6 +335,77 @@ static void pim_rp_check_interfaces(struct pim_instance *pim,
}
}
+void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
+{
+ struct pim_rpf old_rpf;
+ enum pim_rpf_result rpf_result;
+ struct in_addr old_upstream_addr;
+ struct in_addr new_upstream_addr;
+ struct prefix nht_p;
+
+ old_upstream_addr = up->upstream_addr;
+ pim_rp_set_upstream_addr(pim, &new_upstream_addr, up->sg.src,
+ up->sg.grp);
+
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: pim upstream update for old upstream %s",
+ __PRETTY_FUNCTION__,
+ inet_ntoa(old_upstream_addr));
+
+ if (old_upstream_addr.s_addr == new_upstream_addr.s_addr)
+ return;
+
+ /* Lets consider a case, where a PIM upstream has a better RP as a
+ * result of a new RP configuration with more precise group range.
+ * This upstream has to be added to the upstream hash of new RP's
+ * NHT(pnc) and has to be removed from old RP's NHT upstream hash
+ */
+ if (old_upstream_addr.s_addr != INADDR_ANY) {
+ /* Deregister addr with Zebra NHT */
+ nht_p.family = AF_INET;
+ nht_p.prefixlen = IPV4_MAX_BITLEN;
+ nht_p.u.prefix4 = old_upstream_addr;
+ if (PIM_DEBUG_TRACE) {
+ char buf[PREFIX2STR_BUFFER];
+
+ prefix2str(&nht_p, buf, sizeof(buf));
+ zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT",
+ __PRETTY_FUNCTION__, up->sg_str, buf);
+ }
+ pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
+ }
+
+ /* Update the upstream address */
+ up->upstream_addr = new_upstream_addr;
+
+ old_rpf.source_nexthop.interface = up->rpf.source_nexthop.interface;
+
+ rpf_result = pim_rpf_update(pim, up, &old_rpf, 1);
+ if (rpf_result == PIM_RPF_FAILURE)
+ pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
+
+ /* update kernel multicast forwarding cache (MFC) */
+ if (up->rpf.source_nexthop.interface && up->channel_oil) {
+ ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex;
+ int vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex);
+ /* Pass Current selected NH vif index to mroute download */
+ if (vif_index)
+ pim_scan_individual_oil(up->channel_oil, vif_index);
+ else {
+ if (PIM_DEBUG_PIM_NHT)
+ zlog_debug(
+ "%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
+ __PRETTY_FUNCTION__, up->sg_str,
+ up->rpf.source_nexthop.interface->name);
+ }
+ }
+
+ if (rpf_result == PIM_RPF_CHANGED)
+ pim_zebra_upstream_rpf_changed(pim, up, &old_rpf);
+
+ pim_zebra_update_all_interfaces(pim);
+}
+
int pim_rp_new(struct pim_instance *pim, const char *rp,
const char *group_range, const char *plist)
{
@@ -347,6 +420,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
struct prefix temp;
struct pim_nexthop_cache pnc;
struct route_node *rn;
+ struct pim_upstream *up;
+ struct listnode *upnode;
rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
@@ -468,6 +543,27 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
"%s: NHT Register rp_all addr %s grp %s ",
__PRETTY_FUNCTION__, buf, buf1);
}
+
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
+ up)) {
+ /* Find (*, G) upstream whose RP is not
+ * configured yet
+ */
+ if ((up->upstream_addr.s_addr == INADDR_ANY)
+ && (up->sg.src.s_addr == INADDR_ANY)) {
+ struct prefix grp;
+ struct rp_info *trp_info;
+
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = up->sg.grp;
+ trp_info = pim_rp_find_match_group(pim,
+ &grp);
+ if (trp_info == rp_all)
+ pim_upstream_update(pim, up);
+ }
+ }
+
memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
if (pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_all,
&pnc)) {
@@ -535,6 +631,21 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
rn->lock);
}
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
+ if (up->sg.src.s_addr == INADDR_ANY) {
+ struct prefix grp;
+ struct rp_info *trp_info;
+
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = up->sg.grp;
+ trp_info = pim_rp_find_match_group(pim, &grp);
+
+ if (trp_info == rp_info)
+ pim_upstream_update(pim, up);
+ }
+ }
+
/* Register addr with Zebra NHT */
nht_p.family = AF_INET;
nht_p.prefixlen = IPV4_MAX_BITLEN;
@@ -577,6 +688,9 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
struct prefix nht_p;
struct route_node *rn;
bool was_plist = false;
+ struct rp_info *trp_info;
+ struct pim_upstream *up;
+ struct listnode *upnode;
if (group_range == NULL)
result = str2prefix("224.0.0.0/4", &group);
@@ -621,6 +735,23 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
rp_all = pim_rp_find_match_group(pim, &g_all);
if (rp_all == rp_info) {
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
+ /* Find the upstream (*, G) whose upstream address is
+ * same as the deleted RP
+ */
+ if ((up->upstream_addr.s_addr == rp_addr.s_addr) &&
+ (up->sg.src.s_addr == INADDR_ANY)) {
+ struct prefix grp;
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = up->sg.grp;
+ trp_info = pim_rp_find_match_group(pim, &grp);
+ if (trp_info == rp_all) {
+ pim_upstream_rpf_clear(pim, up);
+ up->upstream_addr.s_addr = INADDR_ANY;
+ }
+ }
+ }
rp_all->rp.rpf_addr.family = AF_INET;
rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
rp_all->i_am_rp = 0;
@@ -655,6 +786,34 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
pim_rp_refresh_group_to_rp_mapping(pim);
+ for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
+ /* Find the upstream (*, G) whose upstream address is same as
+ * the deleted RP
+ */
+ if ((up->upstream_addr.s_addr == rp_addr.s_addr) &&
+ (up->sg.src.s_addr == INADDR_ANY)) {
+ struct prefix grp;
+
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = up->sg.grp;
+
+ trp_info = pim_rp_find_match_group(pim, &grp);
+
+ /* RP not found for the group grp */
+ if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) {
+ pim_upstream_rpf_clear(pim, up);
+ pim_rp_set_upstream_addr(pim,
+ &up->upstream_addr,
+ up->sg.src, up->sg.grp);
+ }
+
+ /* RP found for the group grp */
+ else
+ pim_upstream_update(pim, up);
+ }
+ }
+
XFREE(MTYPE_PIM_RP, rp_info);
return PIM_SUCCESS;
}
@@ -681,6 +840,7 @@ void pim_rp_setup(struct pim_instance *pim)
else {
if (PIM_DEBUG_PIM_NHT_RP) {
char buf[PREFIX2STR_BUFFER];
+
prefix2str(&nht_p, buf, sizeof(buf));
zlog_debug(
"%s: NHT Local Nexthop not found for RP %s ",
@@ -869,7 +1029,7 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
* the rp configured and the source address
*
* If we have don't have a RP configured and the source address is *
- * then return failure.
+ * then set the upstream addr as INADDR_ANY and return failure.
*
*/
int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
@@ -890,6 +1050,7 @@ int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug("%s: Received a (*,G) with no RP configured",
__PRETTY_FUNCTION__);
+ up->s_addr = INADDR_ANY;
return 0;
}
@@ -930,34 +1091,13 @@ int pim_rp_config_write(struct pim_instance *pim, struct vty *vty,
return count;
}
-int pim_rp_check_is_my_ip_address(struct pim_instance *pim,
- struct in_addr group,
- struct in_addr dest_addr)
+bool pim_rp_check_is_my_ip_address(struct pim_instance *pim,
+ struct in_addr dest_addr)
{
- struct rp_info *rp_info;
- struct prefix g;
-
- memset(&g, 0, sizeof(g));
- g.family = AF_INET;
- g.prefixlen = 32;
- g.u.prefix4 = group;
-
- rp_info = pim_rp_find_match_group(pim, &g);
- /*
- * See if we can short-cut some?
- * This might not make sense if we ever leave a static RP
- * type of configuration.
- * Note - Premature optimization might bite our patooeys' here.
- */
- if (I_am_RP(pim, group)) {
- if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr)
- return 1;
- }
-
if (if_lookup_exact_address(&dest_addr, AF_INET, pim->vrf_id))
- return 1;
+ return true;
- return 0;
+ return false;
}
void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
@@ -974,7 +1114,7 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
json = json_object_new_object();
else
vty_out(vty,
- "RP address group/prefix-list OIF I am RP\n");
+ "RP address group/prefix-list OIF I am RP\n");
for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (!pim_rpf_addr_is_inaddr_none(&rp_info->rp)) {
@@ -1037,11 +1177,11 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
48));
if (rp_info->rp.source_nexthop.interface)
- vty_out(vty, "%-10s ",
+ vty_out(vty, "%-16s ",
rp_info->rp.source_nexthop
.interface->name);
else
- vty_out(vty, "%-10s ", "(Unknown)");
+ vty_out(vty, "%-16s ", "(Unknown)");
if (rp_info->i_am_rp)
vty_out(vty, "yes\n");
diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h
index 672a696319..e0f8e16be0 100644
--- a/pimd/pim_rp.h
+++ b/pimd/pim_rp.h
@@ -55,9 +55,8 @@ int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group);
void pim_rp_check_on_if_add(struct pim_interface *pim_ifp);
void pim_i_am_rp_re_evaluate(struct pim_instance *pim);
-int pim_rp_check_is_my_ip_address(struct pim_instance *pim,
- struct in_addr group,
- struct in_addr dest_addr);
+bool pim_rp_check_is_my_ip_address(struct pim_instance *pim,
+ struct in_addr dest_addr);
int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
struct in_addr source, struct in_addr group);
@@ -71,4 +70,7 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty,
bool uj);
void pim_resolve_rp_nh(struct pim_instance *pim);
int pim_rp_list_cmp(void *v1, void *v2);
+struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
+ const struct prefix *group);
+void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up);
#endif
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index 814d2e076b..ee145a5b51 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -205,6 +205,12 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
struct prefix src, grp;
bool neigh_needed = true;
+ if (up->upstream_addr.s_addr == INADDR_ANY) {
+ zlog_debug("%s: RP is not configured yet for %s",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return PIM_RPF_OK;
+ }
+
saved.source_nexthop = rpf->source_nexthop;
saved.rpf_addr = rpf->rpf_addr;
@@ -308,6 +314,33 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
}
/*
+ * In the case of RP deletion and RP unreachablity,
+ * uninstall the mroute in the kernel and clear the
+ * rpf information in the pim upstream and pim channel
+ * oil data structure.
+ */
+void pim_upstream_rpf_clear(struct pim_instance *pim,
+ struct pim_upstream *up)
+{
+ if (up->rpf.source_nexthop.interface) {
+ if (up->channel_oil) {
+ up->channel_oil->oil.mfcc_parent = MAXVIFS;
+ pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
+
+ }
+ pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED);
+ up->rpf.source_nexthop.interface = NULL;
+ up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr =
+ PIM_NET_INADDR_ANY;
+ up->rpf.source_nexthop.mrib_metric_preference =
+ router->infinite_assert_metric.metric_preference;
+ up->rpf.source_nexthop.mrib_route_metric =
+ router->infinite_assert_metric.route_metric;
+ up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY;
+ }
+}
+
+/*
RFC 4601: 4.1.6. State Summarization Macros
neighbor RPF'(S,G) {
diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h
index b9fe162f21..a4793df667 100644
--- a/pimd/pim_rpf.h
+++ b/pimd/pim_rpf.h
@@ -64,7 +64,8 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
struct pim_upstream *up, struct pim_rpf *old,
uint8_t is_new);
-
+void pim_upstream_rpf_clear(struct pim_instance *pim,
+ struct pim_upstream *up);
int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf);
int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf);
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index c6ab8f5a2a..2a0804e10b 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -219,17 +219,25 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
pim_msdp_up_del(pim, &up->sg);
}
- /* Deregister addr with Zebra NHT */
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4 = up->upstream_addr;
- if (PIM_DEBUG_TRACE) {
- char buf[PREFIX2STR_BUFFER];
- prefix2str(&nht_p, buf, sizeof(buf));
- zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT",
- __PRETTY_FUNCTION__, up->sg_str, buf);
+ /* When RP gets deleted, pim_rp_del() deregister addr with Zebra NHT
+ * and assign up->upstream_addr as INADDR_ANY.
+ * So before de-registering the upstream address, check if is not equal
+ * to INADDR_ANY. This is done in order to avoid de-registering for
+ * 255.255.255.255 which is maintained for some reason..
+ */
+ if (up->upstream_addr.s_addr != INADDR_ANY) {
+ /* Deregister addr with Zebra NHT */
+ nht_p.family = AF_INET;
+ nht_p.prefixlen = IPV4_MAX_BITLEN;
+ nht_p.u.prefix4 = up->upstream_addr;
+ if (PIM_DEBUG_TRACE) {
+ char buf[PREFIX2STR_BUFFER];
+ prefix2str(&nht_p, buf, sizeof(buf));
+ zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT",
+ __PRETTY_FUNCTION__, up->sg_str, buf);
+ }
+ pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
}
- pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
XFREE(MTYPE_PIM_UPSTREAM, up);
@@ -238,6 +246,13 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
void pim_upstream_send_join(struct pim_upstream *up)
{
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: up %s RPF is not present",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return;
+ }
+
if (PIM_DEBUG_TRACE) {
char rpf_str[PREFIX_STRLEN];
pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str,
@@ -263,6 +278,13 @@ static int on_join_timer(struct thread *t)
up = THREAD_ARG(t);
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: up %s RPF is not present",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return 0;
+ }
+
/*
* In the case of a HFR we will not ahve anyone to send this to.
*/
@@ -284,12 +306,13 @@ static int on_join_timer(struct thread *t)
static void join_timer_stop(struct pim_upstream *up)
{
- struct pim_neighbor *nbr;
+ struct pim_neighbor *nbr = NULL;
THREAD_OFF(up->t_join_timer);
- nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr.u.prefix4);
+ if (up->rpf.source_nexthop.interface)
+ nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
+ up->rpf.rpf_addr.u.prefix4);
if (nbr)
pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
@@ -356,6 +379,13 @@ void pim_upstream_join_suppress(struct pim_upstream *up,
long t_joinsuppress_msec;
long join_timer_remain_msec;
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: up %s RPF is not present",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return;
+ }
+
t_joinsuppress_msec =
MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface),
1000 * holdtime);
@@ -389,6 +419,13 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
long join_timer_remain_msec;
int t_override_msec;
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: up %s RPF is not present",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return;
+ }
+
join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer);
t_override_msec =
pim_if_t_override_msec(up->rpf.source_nexthop.interface);
@@ -511,6 +548,20 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
{
enum pim_upstream_state old_state = up->join_state;
+ if (up->upstream_addr.s_addr == INADDR_ANY) {
+ if (PIM_DEBUG_PIM_EVENTS)
+ zlog_debug("%s: RPF not configured for %s",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return;
+ }
+
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_PIM_EVENTS)
+ zlog_debug("%s: RP not reachable for %s",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return;
+ }
+
if (PIM_DEBUG_PIM_EVENTS) {
zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s",
__PRETTY_FUNCTION__, up->sg_str,
@@ -558,11 +609,14 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
&& !I_am_RP(pim, up->sg.grp)) {
if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug(
- "%s: *,G IIF %s S,G IIF %s ",
- __PRETTY_FUNCTION__,
- up->parent->rpf.source_nexthop
- .interface->name,
- up->rpf.source_nexthop.interface->name);
+ "%s: *,G IIF %s S,G IIF %s ",
+ __PRETTY_FUNCTION__,
+ up->parent->rpf.source_nexthop.interface ?
+ up->parent->rpf.source_nexthop.interface->name
+ : "Unknown",
+ up->rpf.source_nexthop.interface ?
+ up->rpf.source_nexthop.interface->name :
+ "Unknown");
pim_jp_agg_single_upstream_send(&up->parent->rpf,
up->parent,
1 /* (W,G) Join */);
@@ -611,15 +665,14 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
ch->upstream = up;
up = hash_get(pim->upstream_hash, up, hash_alloc_intern);
+ /* Set up->upstream_addr as INADDR_ANY, if RP is not
+ * configured and retain the upstream data structure
+ */
if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src,
sg->grp)) {
if (PIM_DEBUG_TRACE)
zlog_debug("%s: Received a (*,G) with no RP configured",
__PRETTY_FUNCTION__);
-
- hash_release(pim->upstream_hash, up);
- XFREE(MTYPE_PIM_UPSTREAM, up);
- return NULL;
}
up->parent = pim_upstream_find_parent(pim, up);
@@ -659,45 +712,34 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
if (up->sg.src.s_addr != INADDR_ANY)
wheel_add_item(pim->upstream_sg_wheel, up);
- rpf_result = pim_rpf_update(pim, up, NULL, 1);
- if (rpf_result == PIM_RPF_FAILURE) {
- struct prefix nht_p;
-
- if (PIM_DEBUG_TRACE)
- zlog_debug(
- "%s: Attempting to create upstream(%s), Unable to RPF for source",
- __PRETTY_FUNCTION__, up->sg_str);
-
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4 = up->upstream_addr;
- pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
+ if (up->upstream_addr.s_addr == INADDR_ANY)
+ /* Create a dummmy channel oil with incoming ineterface MAXVIFS,
+ * since RP is not configured
+ */
+ up->channel_oil = pim_channel_oil_add(pim, &up->sg, MAXVIFS);
- if (up->parent) {
- listnode_delete(up->parent->sources, up);
- up->parent = NULL;
+ else {
+ rpf_result = pim_rpf_update(pim, up, NULL, 1);
+ if (rpf_result == PIM_RPF_FAILURE) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug(
+ "%s: Attempting to create upstream(%s), Unable to RPF for source",
+ __PRETTY_FUNCTION__, up->sg_str);
+ /* Create a dummmy channel oil with incoming ineterface
+ * MAXVIFS, since RP is not reachable
+ */
+ up->channel_oil = pim_channel_oil_add(
+ pim, &up->sg, MAXVIFS);
}
- if (up->sg.src.s_addr != INADDR_ANY)
- wheel_remove_item(pim->upstream_sg_wheel, up);
-
- pim_upstream_remove_children(pim, up);
- if (up->sources)
- list_delete(&up->sources);
-
- list_delete(&up->ifchannels);
-
- hash_release(pim->upstream_hash, up);
- XFREE(MTYPE_PIM_UPSTREAM, up);
- return NULL;
+ if (up->rpf.source_nexthop.interface) {
+ pim_ifp = up->rpf.source_nexthop.interface->info;
+ if (pim_ifp)
+ up->channel_oil = pim_channel_oil_add(pim,
+ &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(
- pim, &up->sg, pim_ifp->mroute_vif_index);
- }
listnode_add_sort(pim->upstream_list, up);
if (PIM_DEBUG_TRACE) {
@@ -783,7 +825,7 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d",
__PRETTY_FUNCTION__, name,
up->sg_str, buf, up->rpf.source_nexthop.interface ?
- up->rpf.source_nexthop.interface->name : "NIL" ,
+ up->rpf.source_nexthop.interface->name : "Unknown" ,
found, up->ref_count);
} else
zlog_debug("%s(%s): (%s) failure to create",
@@ -896,7 +938,7 @@ void pim_upstream_update_join_desired(struct pim_instance *pim,
PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags);
/* switched from false to true */
- if (is_join_desired && !was_join_desired) {
+ if (is_join_desired && (up->join_state == PIM_UPSTREAM_NOTJOINED)) {
pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
return;
}
@@ -973,7 +1015,9 @@ void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
(old_rpf_ifp == ch->interface) &&
/* RPF_interface(S) stopped being I */
(ch->upstream->rpf.source_nexthop
- .interface != ch->interface)) {
+ .interface) &&
+ (ch->upstream->rpf.source_nexthop
+ .interface != ch->interface)) {
assert_action_a5(ch);
}
} /* PIM_IFASSERT_I_AM_LOSER */
@@ -1339,6 +1383,13 @@ static int pim_upstream_register_stop_timer(struct thread *t)
case PIM_REG_JOIN:
break;
case PIM_REG_PRUNE:
+ if (!up->rpf.source_nexthop.interface) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("%s: up %s RPF is not present",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return 0;
+ }
+
pim_ifp = up->rpf.source_nexthop.interface->info;
if (!pim_ifp) {
if (PIM_DEBUG_TRACE)
@@ -1515,11 +1566,19 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
* Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
*/
for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
+ if (up->upstream_addr.s_addr == INADDR_ANY) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug(
+ "%s: RP not configured for Upstream %s",
+ __PRETTY_FUNCTION__, up->sg_str);
+ continue;
+ }
+
if (pim_rpf_addr_is_inaddr_any(&up->rpf)) {
if (PIM_DEBUG_TRACE)
zlog_debug(
- "Upstream %s without a path to send join, checking",
- up->sg_str);
+ "%s: Upstream %s without a path to send join, checking",
+ __PRETTY_FUNCTION__, up->sg_str);
pim_rpf_update(pim, up, NULL, 1);
}
}
@@ -1586,7 +1645,8 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
/* "iif == RPF_interface(S)" check has to be done by the kernel or hw
* so we will skip that here */
- if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
+ if (up->rpf.source_nexthop.interface &&
+ pim_if_connected_to_source(up->rpf.source_nexthop.interface,
up->sg.src)) {
return true;
}
@@ -1622,7 +1682,7 @@ static void pim_upstream_sg_running(void *arg)
// No packet can have arrived here if this is the case
if (!up->channel_oil->installed) {
if (PIM_DEBUG_TRACE)
- zlog_debug("%s: %s[%s] is not installed in mroute",
+ zlog_debug("%s: %s%s is not installed in mroute",
__PRETTY_FUNCTION__, up->sg_str,
pim->vrf->name);
return;
@@ -1679,7 +1739,8 @@ static void pim_upstream_sg_running(void *arg)
} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
- if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
+ if ((up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) &&
+ (up->rpf.source_nexthop.interface)) {
pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
}
return;
diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h
index f44b95c811..70e70140d1 100644
--- a/pimd/pim_upstream.h
+++ b/pimd/pim_upstream.h
@@ -88,10 +88,30 @@ enum pim_upstream_sptbit {
/*
Upstream (S,G) channel in Joined state
-
(S,G) in the "Not Joined" state is not represented
-
See RFC 4601: 4.5.7. Sending (S,G) Join/Prune Message
+
+ upstream_addr : Who we are talking to.
+ For (*, G), upstream_addr is RP address or INADDR_ANY(if RP not configured)
+ For (S, G), upstream_addr is source address
+
+ rpf: contains the nexthop information to whom we are talking to.
+
+ join_state: JOINED/NOTJOINED
+
+ In the case when FRR receives IGMP/PIM (*, G) join for group G and RP is not
+ configured, then create a pim_upstream with the below information.
+ pim_upstream->upstream address: INADDR_ANY
+ pim_upstream->rpf: Unknown
+ pim_upstream->state: NOTJOINED
+
+ When a new RP gets configured for G, find the corresponding pim upstream (*,G)
+ entries and update the upstream address as new RP address if it the better one
+ for the group G.
+
+ When RP becomes reachable, populate the nexthop information in
+ pim_upstream->rpf and update the state to JOINED.
+
*/
struct pim_upstream {
struct pim_upstream *parent;
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) {
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 0ffe313c17..6d93a40b91 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -499,7 +499,7 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
more.src = c_oil->oil.mfcc_origin;
more.grp = c_oil->oil.mfcc_mcastgrp;
zlog_debug(
- "Sending Request for New Channel Oil Information(%s) VIIF %d(%s)",
+ "Sending Request for New Channel Oil Information%s VIIF %d(%s)",
pim_str_sg_dump(&more), c_oil->oil.mfcc_parent,
c_oil->pim->vrf->name);
}
diff --git a/pimd/pimd.c b/pimd/pimd.c
index 656b000579..889a83a136 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -127,8 +127,6 @@ void pim_terminate(void)
{
struct zclient *zclient;
- pim_free();
-
/* reverse prefix_list_init */
prefix_list_add_hook(NULL);
prefix_list_delete_hook(NULL);
@@ -142,6 +140,8 @@ void pim_terminate(void)
zclient_free(zclient);
}
+ pim_free();
pim_router_terminate();
+
frr_fini();
}