#include "prefix.h"
#include "zclient.h"
#include "plist.h"
+#include "hash.h"
+#include "nexthop.h"
#include "pimd.h"
#include "pim_mroute.h"
#include "pim_rp.h"
#include "pim_zlookup.h"
#include "pim_msdp.h"
+#include "pim_ssm.h"
+#include "pim_nht.h"
static struct cmd_node pim_global_node = {
PIM_NODE,
mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
if (uj) {
+ char pbuf[PREFIX2STR_BUFFER];
json_row = json_object_new_object();
json_object_pim_ifp_add(json_row, ifp);
sec_list = json_object_new_array();
for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) {
- json_object_array_add(sec_list, json_object_new_string(inet_ntoa(sec_addr->addr)));
+ json_object_array_add(sec_list,
+ json_object_new_string(prefix2str(&sec_addr->addr,
+ pbuf,
+ sizeof(pbuf))));
}
json_object_object_add(json_row, "secondaryAddressList", sec_list);
}
vty_out(vty, "Use Source : %s%s", inet_ntoa(pim_ifp->update_source), VTY_NEWLINE);
}
if (pim_ifp->sec_addr_list) {
+ char pbuf[PREFIX2STR_BUFFER];
vty_out(vty, "Address : %s (primary)%s",
- inet_ntoa(ifaddr), VTY_NEWLINE);
+ inet_ntoa(ifaddr), VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) {
vty_out(vty, " %s%s",
- inet_ntoa(sec_addr->addr), VTY_NEWLINE);
+ prefix2str(&sec_addr->addr,
+ pbuf,
+ sizeof(pbuf)), VTY_NEWLINE);
}
} else {
vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE);
struct pim_upstream *up;
int fhr = 0;
int pim_nbrs = 0;
+ int pim_ifchannels = 0;
json_object *json = NULL;
json_object *json_row = NULL;
json_object *json_tmp;
continue;
pim_nbrs = pim_ifp->pim_neighbor_list->count;
+ pim_ifchannels = pim_ifp->pim_ifchannel_list->count;
fhr = 0;
for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up))
json_row = json_object_new_object();
json_object_pim_ifp_add(json_row, ifp);
json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
+ json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
json_object_int_add(json_row, "firstHopRouter", fhr);
json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr));
if (uj) {
vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
} else {
- vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR%s", VTY_NEWLINE);
+ vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR IfChannels%s", VTY_NEWLINE);
json_object_object_foreach(json, key, val) {
vty_out(vty, "%-9s ", key);
}
json_object_object_get_ex(val, "firstHopRouter", &json_tmp);
- vty_out(vty, "%3d%s", json_object_get_int(json_tmp), VTY_NEWLINE);
+ vty_out(vty, "%3d ", json_object_get_int(json_tmp));
+
+ json_object_object_get_ex(val, "pimIfChannels", &json_tmp);
+ vty_out(vty, "%9d%s", json_object_get_int(json_tmp), VTY_NEWLINE);
}
}
json_object_string_add(json_row, "upTime", uptime);
json_object_string_add(json_row, "expire", expire);
json_object_string_add(json_row, "prune", prune);
- json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state));
+ json_object_string_add(json_row, "channelJoinName",
+ pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
json_object_int_add(json_row, "SGRpt", 1);
inet_ntoa(ifaddr),
ch_src_str,
ch_grp_str,
- pim_ifchannel_ifjoin_name(ch->ifjoin_state),
+ pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
uptime,
expire,
prune,
if (uj) {
json = json_object_new_object();
} else {
- vty_out(vty, "%sSource Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE);
+ vty_out(vty, "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)");
+ vty_out(vty, "%sInstalled Source Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE);
}
for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
char grp_str[INET_ADDRSTRLEN];
char src_str[INET_ADDRSTRLEN];
- char in_ifname[16];
- char out_ifname[16];
+ char in_ifname[INTERFACE_NAMSIZ+1];
+ char out_ifname[INTERFACE_NAMSIZ+1];
int oif_vif_index;
struct interface *ifp_in;
first_oif = 1;
- if (!c_oil->installed)
- continue;
-
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str));
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str));
ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
if (!json_ifp_in) {
json_ifp_in = json_object_new_object();
json_object_object_add(json_source, in_ifname, json_ifp_in);
+ json_object_int_add (json_source, "Installed", c_oil->installed);
+ json_object_int_add (json_source, "RefCount", c_oil->oil_ref_count);
+ json_object_int_add (json_source, "OilListSize", c_oil->oil_size);
+ json_object_int_add (json_source, "OilRescan", c_oil->oil_inherited_rescan);
+ json_object_int_add (json_source, "LastUsed", c_oil->cc.lastused);
+ json_object_int_add (json_source, "PacketCount", c_oil->cc.pktcnt);
+ json_object_int_add (json_source, "ByteCount", c_oil->cc.bytecnt);
+ json_object_int_add (json_source, "WrongInterface", c_oil->cc.wrong_if);
}
} else {
- vty_out(vty, "%-15s %-15s %-5s ",
+ vty_out(vty, "%-9d %-15s %-15s %-7s ",
+ c_oil->installed,
src_str,
grp_str,
ifp_in->name);
json_object_string_add(json_ifp_out, "group", grp_str);
json_object_string_add(json_ifp_out, "inboundInterface", in_ifname);
json_object_string_add(json_ifp_out, "outboundInterface", out_ifname);
+ json_object_int_add(json_ifp_out, "installed", c_oil->installed);
json_object_object_add(json_ifp_in, out_ifname, json_ifp_out);
} else {
if (first_oif)
{
first_oif = 0;
- vty_out(vty, "%s", out_ifname);
+ vty_out(vty, "%s(%c%c%c%c)", out_ifname,
+ (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ',
+ (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ',
+ (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ',
+ (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' ');
}
else
- vty_out(vty, ",%s", out_ifname);
+ vty_out(vty, ", %s(%c%c%c%c)", out_ifname,
+ (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ',
+ (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ',
+ (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ',
+ (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' ' );
}
}
neigh_src_str, sizeof(neigh_src_str));
for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) {
- char neigh_sec_str[INET_ADDRSTRLEN];
-
- if (p->family != AF_INET)
- continue;
+ char neigh_sec_str[PREFIX2STR_BUFFER];
- pim_inet4_dump("<src?>", p->u.prefix4,
- neigh_sec_str, sizeof(neigh_sec_str));
+ prefix2str(p, neigh_sec_str, sizeof(neigh_sec_str));
vty_out(vty, "%-9s %-15s %-15s %-15s%s",
ifp->name,
json_object_boolean_true_add(json, "sourceMsdp");
}
+static const char *
+pim_upstream_state2brief_str (enum pim_upstream_state join_state, char *state_str)
+{
+ switch (join_state)
+ {
+ case PIM_UPSTREAM_NOTJOINED:
+ strcpy (state_str, "NotJ");
+ break;
+ case PIM_UPSTREAM_JOINED:
+ strcpy (state_str, "J");
+ break;
+ default:
+ strcpy (state_str, "Unk");
+ }
+ return state_str;
+}
+
+static const char *
+pim_reg_state2brief_str (enum pim_reg_state reg_state, char *state_str)
+{
+ switch (reg_state)
+ {
+ case PIM_REG_NOINFO:
+ strcpy (state_str, "RegNI");
+ break;
+ case PIM_REG_JOIN:
+ strcpy (state_str, "RegJ");
+ break;
+ case PIM_REG_JOIN_PENDING:
+ case PIM_REG_PRUNE:
+ strcpy (state_str, "RegP");
+ break;
+ default:
+ strcpy (state_str, "Unk");
+ }
+ return state_str;
+}
+
static void pim_show_upstream(struct vty *vty, u_char uj)
{
struct listnode *upnode;
char rs_timer[10];
char ka_timer[10];
char msdp_reg_timer[10];
+ char state_str[PIM_REG_STATE_STR_LEN];
pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition);
pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer);
+
+ /*
+ * If we have a J/P timer for the neighbor display that
+ */
+ if (!up->t_join_timer)
+ {
+ struct pim_neighbor *nbr;
+
+ nbr = pim_neighbor_find (up->rpf.source_nexthop.interface,
+ up->rpf.rpf_addr.u.prefix4);
+ if (nbr)
+ pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), nbr->jp_timer);
+ }
+
pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer);
pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer);
pim_time_timer_to_hhmmss (msdp_reg_timer, sizeof (msdp_reg_timer), up->t_msdp_reg_timer);
+ pim_upstream_state2brief_str (up->join_state, state_str);
+ if (up->reg_state != PIM_REG_NOINFO) {
+ char tmp_str[PIM_REG_STATE_STR_LEN];
+
+ sprintf (state_str + strlen (state_str), ",%s",
+ pim_reg_state2brief_str (up->reg_state, tmp_str));
+ }
+
if (uj) {
json_object_object_get_ex(json, grp_str, &json_group);
json_object_string_add(json_row, "inboundInterface", up->rpf.source_nexthop.interface->name);
json_object_string_add(json_row, "source", src_str);
json_object_string_add(json_row, "group", grp_str);
- json_object_string_add(json_row, "state", pim_upstream_state2str (up->join_state));
+ json_object_string_add(json_row, "state", state_str);
+ json_object_string_add(json_row, "joinState", pim_upstream_state2str (up->join_state));
+ json_object_string_add(json_row, "regState", pim_reg_state2str (up->reg_state, state_str));
json_object_string_add(json_row, "upTime", uptime);
json_object_string_add(json_row, "joinTimer", join_timer);
json_object_string_add(json_row, "resetTimer", rs_timer);
up->rpf.source_nexthop.interface->name,
src_str,
grp_str,
- pim_upstream_state2str (up->join_state),
+ state_str,
uptime,
join_timer,
rs_timer,
}
}
+static int
+pim_print_pnc_cache_walkcb (struct hash_backet *backet, void *arg)
+{
+ struct pim_nexthop_cache *pnc = backet->data;
+ struct vty *vty = arg;
+ struct nexthop *nh_node = NULL;
+ ifindex_t first_ifindex;
+ struct interface *ifp = NULL;
+
+ if (!pnc)
+ return CMD_SUCCESS;
+
+ for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next)
+ {
+ first_ifindex = nh_node->ifindex;
+ ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT);
+
+ vty_out (vty, "%-15s ", inet_ntoa (pnc->rpf.rpf_addr.u.prefix4));
+ vty_out (vty, "%-14s ", ifp ? ifp->name : "NULL");
+ vty_out (vty, "%s ", inet_ntoa (nh_node->gate.ipv4));
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+ return CMD_SUCCESS;
+}
+
+static void
+pim_show_nexthop (struct vty *vty)
+{
+
+ if (pimg && !pimg->rpf_hash)
+ {
+ vty_out (vty, "no nexthop cache %s", VTY_NEWLINE);
+ return;
+ }
+
+ vty_out (vty, "Number of registered addresses: %lu %s",
+ pimg->rpf_hash->count, VTY_NEWLINE);
+ vty_out (vty, "Address Interface Nexthop%s", VTY_NEWLINE);
+ vty_out (vty, "-------------------------------------------%s", VTY_NEWLINE);
+
+ hash_walk (pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty);
+
+}
+
static void igmp_show_groups(struct vty *vty, u_char uj)
{
struct listnode *ifnode;
}
}
-static void static_mroute_add_all()
-{
- struct listnode *node;
- struct static_route *s_route;
-
- for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
- if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) {
- /* just log warning */
- char source_str[INET_ADDRSTRLEN];
- char group_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
- pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
- __FILE__, __PRETTY_FUNCTION__,
- source_str, group_str);
- }
- }
-}
-
-static void static_mroute_del_all()
-{
- struct listnode *node;
- struct static_route *s_route;
-
- for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
- if (pim_mroute_del(&s_route->c_oil, __PRETTY_FUNCTION__)) {
- /* just log warning */
- char source_str[INET_ADDRSTRLEN];
- char group_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
- pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
- __FILE__, __PRETTY_FUNCTION__,
- source_str, group_str);
- }
- }
-}
-
DEFUN (clear_ip_mroute,
clear_ip_mroute_cmd,
"clear ip mroute",
if (uj)
argc--;
- if (argc == 5)
+ if (argc == 6)
{
src_or_group = argv[4]->arg;
group = argv[5]->arg;
}
- else if (argc == 4)
+ else if (argc == 5)
src_or_group = argv[4]->arg;
pim_show_state(vty, src_or_group, group, uj);
return CMD_SUCCESS;
}
+DEFUN (show_ip_pim_nexthop,
+ show_ip_pim_nexthop_cmd,
+ "show ip pim nexthop",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ "PIM cached nexthop rpf information\n")
+{
+ pim_show_nexthop (vty);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_nexthop_lookup,
+ show_ip_pim_nexthop_lookup_cmd,
+ "show ip pim nexthop-lookup A.B.C.D A.B.C.D",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ "PIM cached nexthop rpf lookup\n"
+ "Source/RP address\n"
+ "Multicast Group address\n")
+{
+ struct pim_nexthop_cache pnc;
+ struct prefix nht_p;
+ int result = 0;
+ struct in_addr src_addr, grp_addr;
+ struct in_addr vif_source;
+ const char *addr_str, *addr_str1;
+ struct prefix grp;
+ struct pim_nexthop nexthop;
+ char nexthop_addr_str[PREFIX_STRLEN];
+ char grp_str[PREFIX_STRLEN];
+
+ addr_str = (const char *)argv[0];
+ result = inet_pton (AF_INET, addr_str, &src_addr);
+ if (result <= 0)
+ {
+ vty_out (vty, "Bad unicast address %s: errno=%d: %s%s",
+ addr_str, errno, safe_strerror (errno), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (pim_is_group_224_4 (src_addr))
+ {
+ vty_out (vty, "Invalid argument. Expected Valid Source Address.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ addr_str1 = (const char *)argv[1];
+ result = inet_pton (AF_INET, addr_str1, &grp_addr);
+ if (result <= 0)
+ {
+ vty_out (vty, "Bad unicast address %s: errno=%d: %s%s",
+ addr_str, errno, safe_strerror (errno), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!pim_is_group_224_4 (grp_addr))
+ {
+ vty_out (vty, "Invalid argument. Expected Valid Multicast Group Address.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!pim_rp_set_upstream_addr (&vif_source, src_addr, grp_addr))
+ return CMD_SUCCESS;
+
+ memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
+ nht_p.family = AF_INET;
+ nht_p.prefixlen = IPV4_MAX_BITLEN;
+ nht_p.u.prefix4 = vif_source;
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = grp_addr;
+ memset (&nexthop, 0, sizeof (nexthop));
+
+ if ((pim_find_or_track_nexthop (&nht_p, NULL, NULL, &pnc)) == 1)
+ {
+ //Compute PIM RPF using Cached nexthop
+ pim_ecmp_nexthop_search (&pnc, &nexthop, &nht_p, &grp, 0);
+ }
+ else
+ pim_ecmp_nexthop_lookup (&nexthop, vif_source, &nht_p, &grp, 0);
+
+ pim_addr_dump ("<grp?>", &grp, grp_str, sizeof (grp_str));
+ pim_addr_dump ("<nexthop?>", &nexthop.mrib_nexthop_addr,
+ nexthop_addr_str, sizeof (nexthop_addr_str));
+ vty_out (vty, "Group %s --- Nexthop %s Interface %s %s", grp_str,
+ nexthop_addr_str, nexthop.interface->name, VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
static void show_multicast_interfaces(struct vty *vty)
{
struct listnode *node;
{
time_t now = pim_time_monotonic_sec();
- if (PIM_MROUTE_IS_ENABLED) {
- char uptime[10];
+ char uptime[10];
- vty_out(vty, "Mroute socket descriptor: %d%s",
- qpim_mroute_socket_fd,
- VTY_NEWLINE);
+ vty_out(vty, "Mroute socket descriptor: %d%s",
+ qpim_mroute_socket_fd,
+ VTY_NEWLINE);
- pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation);
- vty_out(vty, "Mroute socket uptime: %s%s",
- uptime,
- VTY_NEWLINE);
- }
- else {
- vty_out(vty, "Multicast disabled%s",
- VTY_NEWLINE);
- }
+ pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation);
+ vty_out(vty, "Mroute socket uptime: %s%s",
+ uptime,
+ VTY_NEWLINE);
vty_out(vty, "%s", VTY_NEWLINE);
- vty_out(vty, "Zclient update socket: ");
- if (qpim_zclient_update) {
- vty_out(vty, "%d failures=%d%s", qpim_zclient_update->sock,
- qpim_zclient_update->fail, VTY_NEWLINE);
- }
- else {
- vty_out(vty, "<null zclient>%s", VTY_NEWLINE);
- }
+ pim_zebra_zclient_update (vty);
pim_zlookup_show_ip_multicast (vty);
vty_out(vty, "%s", VTY_NEWLINE);
- vty_out(vty, "Current highest VifIndex: %d%s",
- qpim_mroute_oif_highest_vif_index,
- VTY_NEWLINE);
vty_out(vty, "Maximum highest VifIndex: %d%s",
PIM_MAX_USABLE_VIFS,
VTY_NEWLINE);
- vty_out(vty, "%s", VTY_NEWLINE);
- vty_out(vty, "Upstream Join Timer: %d secs%s",
- qpim_t_periodic,
- VTY_NEWLINE);
- vty_out(vty, "Join/Prune Holdtime: %d secs%s",
- PIM_JP_HOLDTIME,
- VTY_NEWLINE);
+ vty_out (vty, "%s", VTY_NEWLINE);
+ vty_out (vty, "Upstream Join Timer: %d secs%s",
+ qpim_t_periodic, VTY_NEWLINE);
+ vty_out (vty, "Join/Prune Holdtime: %d secs%s",
+ PIM_JP_HOLDTIME, VTY_NEWLINE);
+ vty_out (vty, "PIM ECMP: %s%s",
+ qpim_ecmp_enable ? "Enable" : "Disable", VTY_NEWLINE);
+ vty_out (vty, "PIM ECMP Rebalance: %s%s",
+ qpim_ecmp_rebalance_enable ? "Enable" : "Disable", VTY_NEWLINE);
- vty_out(vty, "%s", VTY_NEWLINE);
+ vty_out (vty, "%s", VTY_NEWLINE);
show_rpf_refresh_stats(vty, now, NULL);
json_object *json_ifp_out = NULL;
int found_oif = 0;
int first = 1;
+ char grp_str[INET_ADDRSTRLEN];
+ char src_str[INET_ADDRSTRLEN];
+ char in_ifname[INTERFACE_NAMSIZ+1];
+ char out_ifname[INTERFACE_NAMSIZ+1];
+ int oif_vif_index;
+ struct interface *ifp_in;
+ char proto[100];
if (uj) {
json = json_object_new_object();
/* print list of PIM and IGMP routes */
for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
- char grp_str[INET_ADDRSTRLEN];
- char src_str[INET_ADDRSTRLEN];
- char in_ifname[16];
- char out_ifname[16];
- int oif_vif_index;
- char proto[100];
- struct interface *ifp_in;
found_oif = 0;
first = 1;
if (!c_oil->installed && !uj)
if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE)
json_object_boolean_true_add(json_ifp_out, "protocolSource");
+ if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR)
+ json_object_boolean_true_add(json_ifp_out, "protocolInherited");
+
json_object_string_add(json_ifp_out, "inboundInterface", in_ifname);
json_object_int_add(json_ifp_out, "iVifI", c_oil->oil.mfcc_parent);
json_object_string_add(json_ifp_out, "outboundInterface", out_ifname);
strcpy(proto, "SRC");
}
+ if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) {
+ strcpy(proto, "STAR");
+ }
+
vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s",
src_str,
grp_str,
/* Print list of static routes */
for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
- char grp_str[INET_ADDRSTRLEN];
- char src_str[INET_ADDRSTRLEN];
- char in_ifname[16];
- char out_ifname[16];
- int oif_vif_index;
- struct interface *ifp_in;
- char proto[100];
first = 1;
if (!s_route->c_oil.installed)
return CMD_SUCCESS;
}
+DEFUN (ip_pim_spt_switchover_infinity,
+ ip_pim_spt_switchover_infinity_cmd,
+ "ip pim spt-switchover infinity-and-beyond",
+ IP_STR
+ PIM_STR
+ "SPT-Switchover\n"
+ "Never switch to SPT Tree\n")
+{
+ pimg->spt_switchover = PIM_SPT_INFINITY;
+
+ pim_upstream_remove_lhr_star_pimreg();
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_spt_switchover_infinity,
+ no_ip_pim_spt_switchover_infinity_cmd,
+ "no ip pim spt-switchover infinity-and-beyond",
+ NO_STR
+ IP_STR
+ PIM_STR
+ "SPT_Switchover\n"
+ "Never switch to SPT Tree\n")
+{
+ pimg->spt_switchover = PIM_SPT_IMMEDIATE;
+
+ pim_upstream_add_lhr_star_pimreg();
+ return CMD_SUCCESS;
+}
+
DEFUN (ip_pim_joinprune_time,
ip_pim_joinprune_time_cmd,
"ip pim join-prune-interval <60-600>",
return CMD_SUCCESS;
}
+DEFUN (ip_pim_v6_secondary,
+ ip_pim_v6_secondary_cmd,
+ "ip pim send-v6-secondary",
+ IP_STR
+ "pim multicast routing\n"
+ "Send v6 secondary addresses\n")
+{
+ pimg->send_v6_secondary = 1;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_v6_secondary,
+ no_ip_pim_v6_secondary_cmd,
+ "no ip pim send-v6-secondary",
+ NO_STR
+ IP_STR
+ "pim multicast routing\n"
+ "Send v6 secondary addresses\n")
+{
+ pimg->send_v6_secondary = 0;
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ip_pim_rp,
ip_pim_rp_cmd,
"ip pim rp A.B.C.D [A.B.C.D/M]",
"ip address of RP\n"
"Group Address range to cover\n")
{
- int idx_ipv4 = 4;
+ int idx_ipv4 = 4, idx_group = 0;
- if (argc == (idx_ipv4 + 1))
- return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
+ if (argv_find (argv, argc, "A.B.C.D/M", &idx_group))
+ return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_group]->arg, NULL);
else
return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL);
}
return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg);
}
-DEFUN (ip_multicast_routing,
- ip_multicast_routing_cmd,
- "ip multicast-routing",
+static int
+pim_ssm_cmd_worker (struct vty *vty, const char *plist)
+{
+ int result = pim_ssm_range_set (VRF_DEFAULT, plist);
+
+ if (result == PIM_SSM_ERR_NONE)
+ return CMD_SUCCESS;
+
+ switch (result)
+ {
+ case PIM_SSM_ERR_NO_VRF:
+ vty_out (vty, "%% VRF doesn't exist%s", VTY_NEWLINE);
+ break;
+ case PIM_SSM_ERR_DUP:
+ vty_out (vty, "%% duplicate config%s", VTY_NEWLINE);
+ break;
+ default:
+ vty_out (vty, "%% ssm range config failed%s", VTY_NEWLINE);
+ }
+
+ return CMD_WARNING;
+}
+
+DEFUN (ip_pim_ssm_prefix_list,
+ ip_pim_ssm_prefix_list_cmd,
+ "ip pim ssm prefix-list WORD",
IP_STR
- "Enable IP multicast forwarding\n")
+ "pim multicast routing\n"
+ "Source Specific Multicast\n"
+ "group range prefix-list filter\n"
+ "Name of a prefix-list\n")
{
- pim_mroute_socket_enable();
- pim_if_add_vif_all();
- mroute_add_all();
- static_mroute_add_all();
- return CMD_SUCCESS;
+ return pim_ssm_cmd_worker (vty, argv[0]->arg);
}
-DEFUN (no_ip_multicast_routing,
- no_ip_multicast_routing_cmd,
- "no ip multicast-routing",
+DEFUN (no_ip_pim_ssm_prefix_list,
+ no_ip_pim_ssm_prefix_list_cmd,
+ "no ip pim ssm prefix-list",
NO_STR
IP_STR
- "Global IP configuration subcommands\n"
- "Enable IP multicast forwarding\n")
+ "pim multicast routing\n"
+ "Source Specific Multicast\n"
+ "group range prefix-list filter\n")
{
- mroute_del_all();
- static_mroute_del_all();
- pim_if_del_vif_all();
- pim_mroute_socket_disable();
+ return pim_ssm_cmd_worker (vty, NULL);
+}
+
+DEFUN (no_ip_pim_ssm_prefix_list_name,
+ no_ip_pim_ssm_prefix_list_name_cmd,
+ "no ip pim ssm prefix-list WORD",
+ NO_STR
+ IP_STR
+ "pim multicast routing\n"
+ "Source Specific Multicast\n"
+ "group range prefix-list filter\n"
+ "Name of a prefix-list\n")
+{
+ struct pim_ssm *ssm = pimg->ssm_info;
+
+ if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg))
+ return pim_ssm_cmd_worker (vty, NULL);
+
+ vty_out (vty, "%% pim ssm prefix-list %s doesn't exist%s",
+ argv[0]->arg, VTY_NEWLINE);
+
+ return CMD_WARNING;
+}
+
+static void
+ip_pim_ssm_show_group_range(struct vty *vty, u_char uj)
+{
+ struct pim_ssm *ssm = pimg->ssm_info;
+ const char *range_str = ssm->plist_name?ssm->plist_name:PIM_SSM_STANDARD_RANGE;
+
+ if (uj)
+ {
+ json_object *json;
+ json = json_object_new_object();
+ json_object_string_add(json, "ssmGroups", range_str);
+ vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
+ json_object_free(json);
+ }
+ else
+ vty_out(vty, "SSM group range : %s%s", range_str, VTY_NEWLINE);
+}
+
+DEFUN (show_ip_pim_ssm_range,
+ show_ip_pim_ssm_range_cmd,
+ "show ip pim group-type [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ "PIM group type\n"
+ "JavaScript Object Notation\n")
+{
+ u_char uj = use_json(argc, argv);
+ ip_pim_ssm_show_group_range(vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+static void
+ip_pim_ssm_show_group_type(struct vty *vty, u_char uj, const char *group)
+{
+ struct in_addr group_addr;
+ const char *type_str;
+ int result;
+
+ result = inet_pton(AF_INET, group, &group_addr);
+ if (result <= 0)
+ type_str = "invalid";
+ else
+ {
+ if (pim_is_group_224_4 (group_addr))
+ type_str = pim_is_grp_ssm (group_addr)?"SSM":"ASM";
+ else
+ type_str = "not-multicast";
+ }
+
+ if (uj)
+ {
+ json_object *json;
+ json = json_object_new_object();
+ json_object_string_add(json, "groupType", type_str);
+ vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
+ json_object_free(json);
+ }
+ else
+ vty_out(vty, "Group type : %s%s", type_str, VTY_NEWLINE);
+}
+
+DEFUN (show_ip_pim_group_type,
+ show_ip_pim_group_type_cmd,
+ "show ip pim group-type A.B.C.D [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ "multicast group type\n"
+ "group address\n"
+ "JavaScript Object Notation\n")
+{
+ u_char uj = use_json(argc, argv);
+ ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN (ip_multicast_routing,
+ ip_multicast_routing_cmd,
+ "ip multicast-routing",
+ IP_STR
+ "Enable IP multicast forwarding\n")
+{
+ return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN (no_ip_multicast_routing,
+ no_ip_multicast_routing_cmd,
+ "no ip multicast-routing",
+ NO_STR
+ IP_STR
+ "Global IP configuration subcommands\n"
+ "Enable IP multicast forwarding\n")
+{
+ vty_out (vty, "Command is Disabled and will be removed in a future version%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
return CMD_SUCCESS;
}
-DEFUN (interface_ip_igmp,
- interface_ip_igmp_cmd,
- "ip igmp",
+DEFUN (ip_pim_ecmp,
+ ip_pim_ecmp_cmd,
+ "ip pim ecmp",
IP_STR
- IFACE_IGMP_STR)
+ "pim multicast routing\n"
+ "Enable PIM ECMP \n")
+{
+ qpim_ecmp_enable = 1;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_ecmp,
+ no_ip_pim_ecmp_cmd,
+ "no ip pim ecmp",
+ NO_STR
+ IP_STR
+ "pim multicast routing\n"
+ "Disable PIM ECMP \n")
+{
+ qpim_ecmp_enable = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (ip_pim_ecmp_rebalance,
+ ip_pim_ecmp_rebalance_cmd,
+ "ip pim ecmp rebalance",
+ IP_STR
+ "pim multicast routing\n"
+ "Enable PIM ECMP \n"
+ "Enable PIM ECMP Rebalance\n")
+{
+ qpim_ecmp_rebalance_enable = 1;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_ecmp_rebalance,
+ no_ip_pim_ecmp_rebalance_cmd,
+ "no ip pim ecmp rebalance",
+ NO_STR
+ IP_STR
+ "pim multicast routing\n"
+ "Disable PIM ECMP \n"
+ "Disable PIM ECMP Rebalance\n")
+{
+ qpim_ecmp_rebalance_enable = 0;
+
+ return CMD_SUCCESS;
+}
+
+static int
+pim_cmd_igmp_start (struct vty *vty, struct interface *ifp)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
struct pim_interface *pim_ifp;
pim_ifp = ifp->info;
return CMD_SUCCESS;
}
+DEFUN (interface_ip_igmp,
+ interface_ip_igmp_cmd,
+ "ip igmp",
+ IP_STR
+ IFACE_IGMP_STR)
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+
+ return pim_cmd_igmp_start(vty, ifp);
+}
+
DEFUN (interface_no_ip_igmp,
interface_no_ip_igmp_cmd,
"no ip igmp",
struct pim_interface *pim_ifp;
int query_interval;
int query_interval_dsec;
+ int ret;
pim_ifp = ifp->info;
if (!pim_ifp) {
- vty_out(vty,
- "IGMP not enabled on interface %s. Please enable IGMP first.%s",
- ifp->name,
- VTY_NEWLINE);
- return CMD_WARNING;
+ ret = pim_cmd_igmp_start(vty, ifp);
+ if (ret != CMD_SUCCESS)
+ return ret;
+ pim_ifp = ifp->info;
}
query_interval = atoi(argv[3]->arg);
VTY_DECLVAR_CONTEXT(interface,ifp);
struct pim_interface *pim_ifp;
int igmp_version;
+ int ret;
pim_ifp = ifp->info;
if (!pim_ifp) {
- vty_out(vty,
- "IGMP not enabled on interface %s. Please enable IGMP first.%s",
- ifp->name,
- VTY_NEWLINE);
- return CMD_WARNING;
+ ret = pim_cmd_igmp_start(vty, ifp);
+ if (ret != CMD_SUCCESS)
+ return ret;
+ pim_ifp = ifp->info;
}
igmp_version = atoi(argv[3]->arg);
VTY_DECLVAR_CONTEXT(interface, ifp);
struct pim_interface *pim_ifp;
int query_max_response_time;
+ int ret;
pim_ifp = ifp->info;
if (!pim_ifp) {
- vty_out(vty,
- "IGMP not enabled on interface %s. Please enable IGMP first.%s",
- ifp->name,
- VTY_NEWLINE);
- return CMD_WARNING;
+ ret = pim_cmd_igmp_start(vty, ifp);
+ if (ret != CMD_SUCCESS)
+ return ret;
+ pim_ifp = ifp->info;
}
query_max_response_time = atoi(argv[3]->arg);
struct pim_interface *pim_ifp;
int query_max_response_time_dsec;
int default_query_interval_dsec;
+ int ret;
pim_ifp = ifp->info;
if (!pim_ifp) {
- vty_out(vty,
- "IGMP not enabled on interface %s. Please enable IGMP first.%s",
- ifp->name,
- VTY_NEWLINE);
- return CMD_WARNING;
+ ret = pim_cmd_igmp_start(vty, ifp);
+ if (ret != CMD_SUCCESS)
+ return ret;
+ pim_ifp = ifp->info;
}
query_max_response_time_dsec = atoi(argv[4]->arg);
}
static int
-pim_cmd_interface_add (struct interface *ifp, enum pim_interface_type itype)
+pim_cmd_interface_add (struct interface *ifp)
{
struct pim_interface *pim_ifp = ifp->info;
PIM_IF_DO_PIM(pim_ifp->options);
}
- pim_ifp->itype = itype;
pim_if_addr_add_all(ifp);
pim_if_membership_refresh(ifp);
return 1;
}
-
-DEFUN (interface_ip_pim_ssm,
+DEFUN_HIDDEN (interface_ip_pim_ssm,
interface_ip_pim_ssm_cmd,
"ip pim ssm",
IP_STR
{
VTY_DECLVAR_CONTEXT(interface, ifp);
- if (!pim_cmd_interface_add(ifp, PIM_INTERFACE_SSM)) {
- vty_out(vty, "Could not enable PIM SSM on interface%s", VTY_NEWLINE);
+ if (!pim_cmd_interface_add(ifp)) {
+ vty_out(vty, "Could not enable PIM SM on interface%s", VTY_NEWLINE);
return CMD_WARNING;
}
+ vty_out(vty, "WARN: Enabled PIM SM on interface; configure PIM SSM range if needed%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
IFACE_PIM_SM_STR)
{
VTY_DECLVAR_CONTEXT(interface, ifp);
- if (!pim_cmd_interface_add(ifp, PIM_INTERFACE_SM)) {
+ if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface%s", VTY_NEWLINE);
return CMD_WARNING;
}
return 1;
}
-DEFUN (interface_no_ip_pim_ssm,
+DEFUN_HIDDEN (interface_no_ip_pim_ssm,
interface_no_ip_pim_ssm_cmd,
"no ip pim ssm",
NO_STR
int result;
oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname);
+ oif = if_lookup_by_name(oifname, VRF_DEFAULT);
if (!oif) {
vty_out(vty, "No such interface name %s%s",
oifname, VTY_NEWLINE);
int result;
oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname);
+ oif = if_lookup_by_name(oifname, VRF_DEFAULT);
if (!oif) {
vty_out(vty, "No such interface name %s%s",
oifname, VTY_NEWLINE);
int result;
oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname);
+ oif = if_lookup_by_name(oifname, VRF_DEFAULT);
if (!oif) {
vty_out(vty, "No such interface name %s%s",
oifname, VTY_NEWLINE);
int result;
oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname);
+ oif = if_lookup_by_name(oifname, VRF_DEFAULT);
if (!oif) {
vty_out(vty, "No such interface name %s%s",
oifname, VTY_NEWLINE);
DEBUG_PIM_J_P_PACKETS_STR
DEBUG_PIM_PIM_REG_PACKETS_STR)
{
- int idx;
+ int idx = 0;
if (argv_find (argv, argc, "hello", &idx))
{
PIM_DO_DEBUG_PIM_HELLO;
DEFUN (show_ip_msdp_sa_sg,
show_ip_msdp_sa_sg_cmd,
- "show ip msdp sa [A.B.C.D] [A.B.C.D] [json]",
+ "show ip msdp sa [A.B.C.D [A.B.C.D]] [json]",
SHOW_STR
IP_STR
MSDP_STR
"JavaScript Object Notation\n")
{
u_char uj = use_json(argc, argv);
- if (uj)
- argc--;
- if (argc == 5)
- ip_msdp_show_sa_sg(vty, argv[4]->arg, argv[5]->arg, uj);
- else if (argc == 4)
- ip_msdp_show_sa_addr(vty, argv[4]->arg, uj);
+ int idx = 0;
+ char *src_ip = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg : NULL;
+ char *grp_ip = idx < argc && argv_find (argv, argc, "A.B.C.D", &idx) ?
+ argv[idx]->arg : NULL;
+
+ if (src_ip && grp_ip)
+ ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj);
+ else if (src_ip)
+ ip_msdp_show_sa_addr(vty, src_ip, uj);
else
ip_msdp_show_sa(vty, uj);
install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
+ install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
+ install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
+ install_element (CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd);
install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
+ install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
+ install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
install_element (CONFIG_NODE, &ip_pim_packets_cmd);
install_element (CONFIG_NODE, &no_ip_pim_packets_cmd);
+ install_element (CONFIG_NODE, &ip_pim_v6_secondary_cmd);
+ install_element (CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
install_element (CONFIG_NODE, &ip_ssmpingd_cmd);
install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd);
install_element (CONFIG_NODE, &ip_msdp_peer_cmd);
install_element (CONFIG_NODE, &no_ip_msdp_peer_cmd);
+ install_element (CONFIG_NODE, &ip_pim_ecmp_cmd);
+ install_element (CONFIG_NODE, &no_ip_pim_ecmp_cmd);
+ install_element (CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
+ install_element (CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
install_element (INTERFACE_NODE, &interface_ip_igmp_cmd);
install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd);
install_element (VIEW_NODE, &show_ip_rib_cmd);
install_element (VIEW_NODE, &show_ip_ssmpingd_cmd);
install_element (VIEW_NODE, &show_debugging_pim_cmd);
+ install_element (VIEW_NODE, &show_ip_pim_nexthop_cmd);
+ install_element (VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
install_element (ENABLE_NODE, &clear_ip_interfaces_cmd);
install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
install_element (VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
+ install_element (VIEW_NODE, &show_ip_pim_ssm_range_cmd);
+ install_element (VIEW_NODE, &show_ip_pim_group_type_cmd);
install_element (INTERFACE_NODE, &interface_pim_use_source_cmd);
install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd);
}