X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=pimd%2Fpim_cmd.c;h=da07dcb4acbe769021e4045eceb8378ba00b21a6;hb=934ec54171eb067277a46427acd96b4c3cfde2c1;hp=0895ce21cfac6fd4d2e9159473e6f0bf5c5d8c47;hpb=0c2ebf00a628772c09ec97f970ae34b8076e9976;p=mirror_frr.git diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 0895ce21c..da07dcb4a 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1,22 +1,21 @@ /* - PIM for Quagga - Copyright (C) 2008 Everton da Silva Marques - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING; if not, write to the - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - MA 02110-1301 USA -*/ + * PIM for Quagga + * Copyright (C) 2008 Everton da Silva Marques + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include @@ -26,6 +25,8 @@ #include "prefix.h" #include "zclient.h" #include "plist.h" +#include "hash.h" +#include "nexthop.h" #include "pimd.h" #include "pim_mroute.h" @@ -54,6 +55,8 @@ #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, @@ -816,6 +819,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch 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); @@ -827,7 +831,10 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch 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); } @@ -918,11 +925,14 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch 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); @@ -1039,6 +1049,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) 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; @@ -1055,6 +1066,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) 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)) @@ -1065,6 +1077,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) 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)); @@ -1077,7 +1090,7 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) 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); @@ -1099,13 +1112,173 @@ static void pim_show_interfaces(struct vty *vty, u_char uj) } 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_free(json); } +static void pim_show_interface_traffic (struct vty *vty, u_char uj) +{ + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct listnode *node = NULL; + json_object *json = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object (); + else + { + vty_out (vty, "%s", VTY_NEWLINE); + vty_out (vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s%s", "Interface", + " HELLO", " JOIN", " PRUNE", " REGISTER", + " REGISTER-STOP", " ASSERT", VTY_NEWLINE); + vty_out (vty, + "%-10s%-18s%-17s%-17s%-17s%-17s%-17s%s", + "", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", + " Rx/Tx", " Rx/Tx", VTY_NEWLINE); + vty_out (vty, + "---------------------------------------------------------------------------------------------------------------%s", + VTY_NEWLINE); + } + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) + { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + if (uj) + { + json_row = json_object_new_object (); + json_object_pim_ifp_add (json_row, ifp); + json_object_int_add (json_row, "helloRx", pim_ifp->pim_ifstat_hello_recv); + json_object_int_add (json_row, "helloTx", pim_ifp->pim_ifstat_hello_sent); + json_object_int_add (json_row, "joinRx", pim_ifp->pim_ifstat_join_recv); + json_object_int_add (json_row, "joinTx", pim_ifp->pim_ifstat_join_send); + json_object_int_add (json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); + json_object_int_add (json_row, "registerTx", pim_ifp->pim_ifstat_reg_recv); + json_object_int_add (json_row, "registerStopRx", pim_ifp->pim_ifstat_reg_stop_recv); + json_object_int_add (json_row, "registerStopTx", pim_ifp->pim_ifstat_reg_stop_send); + json_object_int_add (json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); + json_object_int_add (json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); + + 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 %s", + ifp->name, pim_ifp->pim_ifstat_hello_recv, + pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, + pim_ifp->pim_ifstat_join_send, pim_ifp->pim_ifstat_prune_recv, + pim_ifp->pim_ifstat_prune_send, pim_ifp->pim_ifstat_reg_recv, + pim_ifp->pim_ifstat_reg_send, + pim_ifp->pim_ifstat_reg_stop_recv, + pim_ifp->pim_ifstat_reg_stop_send, + pim_ifp->pim_ifstat_assert_recv, + pim_ifp->pim_ifstat_assert_send, VTY_NEWLINE); + } + } + if (uj) + { + vty_out (vty, "%s%s", json_object_to_json_string_ext (json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free (json); + } +} + +static void pim_show_interface_traffic_single (struct vty *vty, const char *ifname, u_char uj) +{ + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct listnode *node = NULL; + json_object *json = NULL; + json_object *json_row = NULL; + uint8_t found_ifname = 0; + + if (uj) + json = json_object_new_object (); + else + { + vty_out (vty, "%s", VTY_NEWLINE); + vty_out (vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s%s", "Interface", + " HELLO", " JOIN", " PRUNE", " REGISTER", + " REGISTER-STOP", " ASSERT", VTY_NEWLINE); + vty_out (vty, + "%-10s%-18s%-17s%-17s%-17s%-17s%-17s%s", + "", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", + " Rx/Tx", " Rx/Tx", VTY_NEWLINE); + vty_out (vty, + "---------------------------------------------------------------------------------------------------------------%s", + VTY_NEWLINE); + } + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) + { + if (strcmp (ifname, ifp->name)) + continue; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + found_ifname = 1; + if (uj) + { + json_row = json_object_new_object (); + json_object_pim_ifp_add (json_row, ifp); + json_object_int_add (json_row, "helloRx", pim_ifp->pim_ifstat_hello_recv); + json_object_int_add (json_row, "helloTx", pim_ifp->pim_ifstat_hello_sent); + json_object_int_add (json_row, "joinRx", pim_ifp->pim_ifstat_join_recv); + json_object_int_add (json_row, "joinTx", pim_ifp->pim_ifstat_join_send); + json_object_int_add (json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); + json_object_int_add (json_row, "registerTx", pim_ifp->pim_ifstat_reg_recv); + json_object_int_add (json_row, "registerStopRx", pim_ifp->pim_ifstat_reg_stop_recv); + json_object_int_add (json_row, "registerStopTx", pim_ifp->pim_ifstat_reg_stop_send); + json_object_int_add (json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); + json_object_int_add (json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); + + 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 %s", + ifp->name, pim_ifp->pim_ifstat_hello_recv, + pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, + pim_ifp->pim_ifstat_join_send, pim_ifp->pim_ifstat_prune_recv, + pim_ifp->pim_ifstat_prune_send, pim_ifp->pim_ifstat_reg_recv, + pim_ifp->pim_ifstat_reg_send, + pim_ifp->pim_ifstat_reg_stop_recv, + pim_ifp->pim_ifstat_reg_stop_send, + pim_ifp->pim_ifstat_assert_recv, + pim_ifp->pim_ifstat_assert_send, VTY_NEWLINE); + } + } + if (uj) + { + vty_out (vty, "%s%s", json_object_to_json_string_ext (json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); + json_object_free (json); + } + else + { + if (!found_ifname) + vty_out (vty, "%% No such interface%s", VTY_NEWLINE); + } +} + static void pim_show_join(struct vty *vty, u_char uj) { struct pim_interface *pim_ifp; @@ -1168,7 +1341,8 @@ static void pim_show_join(struct vty *vty, u_char uj) 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); @@ -1187,7 +1361,7 @@ static void pim_show_join(struct vty *vty, u_char uj) 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, @@ -1422,6 +1596,14 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c 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, "%-9d %-15s %-15s %-7s ", @@ -1598,13 +1780,9 @@ static void pim_show_neighbors_secondary(struct vty *vty) neigh_src_str, sizeof(neigh_src_str)); for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) { - char neigh_sec_str[INET_ADDRSTRLEN]; + char neigh_sec_str[PREFIX2STR_BUFFER]; - if (p->family != AF_INET) - continue; - - pim_inet4_dump("", 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, @@ -1643,6 +1821,44 @@ json_object_pim_upstream_add (json_object *json, struct pim_upstream *up) 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; @@ -1691,10 +1907,13 @@ static void pim_show_upstream(struct vty *vty, u_char uj) 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); - if (pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) - pim_reg_state2str (up->reg_state, state_str); - else - strcpy (state_str, pim_upstream_state2str (up->join_state)); + 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); @@ -2008,6 +2227,50 @@ static void pim_show_rpf(struct vty *vty, u_char uj) } } +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; @@ -2390,6 +2653,45 @@ DEFUN (clear_ip_pim_interfaces, return CMD_SUCCESS; } +DEFUN (clear_ip_pim_interface_traffic, + clear_ip_pim_interface_traffic_cmd, + "clear ip pim interface traffic", + "Reset functions\n" + "IP information\n" + "PIM clear commands\n" + "Reset PIM interfaces\n" + "Reset Protocol Packet counters\n") +{ + struct listnode *ifnode = NULL; + struct listnode *ifnextnode = NULL; + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + + for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) + { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + pim_ifp->pim_ifstat_hello_recv = 0; + pim_ifp->pim_ifstat_hello_sent = 0; + pim_ifp->pim_ifstat_join_recv = 0; + pim_ifp->pim_ifstat_join_send = 0; + pim_ifp->pim_ifstat_prune_recv = 0; + pim_ifp->pim_ifstat_prune_send = 0; + pim_ifp->pim_ifstat_reg_recv = 0; + pim_ifp->pim_ifstat_reg_send = 0; + pim_ifp->pim_ifstat_reg_stop_recv = 0; + pim_ifp->pim_ifstat_reg_stop_send = 0; + pim_ifp->pim_ifstat_assert_recv = 0; + pim_ifp->pim_ifstat_assert_send = 0; + + } + + return CMD_SUCCESS; +} + DEFUN (clear_ip_pim_oil, clear_ip_pim_oil_cmd, "clear ip pim oil", @@ -2742,6 +3044,121 @@ DEFUN (show_ip_pim_rpf, 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 = argv[4]->arg; + 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 = argv[5]->arg; + 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_str, sizeof (grp_str)); + pim_addr_dump ("", &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; +} + +DEFUN (show_ip_pim_interface_traffic, + show_ip_pim_interface_traffic_cmd, + "show ip pim interface traffic [WORD] [json]", + SHOW_STR + IP_STR + PIM_STR + "PIM interface information\n" + "Protocol Packet counters\n" + "Interface name\n" + "JavaScript Object Notation\n") +{ + u_char uj = use_json (argc, argv); + int idx = 0; + + if (argv_find(argv, argc, "WORD", &idx)) + pim_show_interface_traffic_single (vty, argv[idx]->arg, uj); + else + pim_show_interface_traffic (vty, uj); + + return CMD_SUCCESS; +} + static void show_multicast_interfaces(struct vty *vty) { struct listnode *node; @@ -2820,15 +3237,17 @@ DEFUN (show_ip_multicast, 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); @@ -3075,7 +3494,7 @@ static void show_mroute(struct vty *vty, u_char uj) json_object_string_add(json_ifp_out, "group", grp_str); json_object_boolean_true_add(json_ifp_out, "protocolStatic"); 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_int_add(json_ifp_out, "iVifI", s_route->c_oil.oil.mfcc_parent); json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); json_object_int_add(json_ifp_out, "ttl", ttl); @@ -3359,9 +3778,86 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const cha return CMD_SUCCESS; } +static int +pim_cmd_spt_switchover (enum pim_spt_switchover spt, const char *plist) +{ + pimg->spt.switchover = spt; + + switch (pimg->spt.switchover) + { + case PIM_SPT_IMMEDIATE: + if (pimg->spt.plist) + XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); + + pim_upstream_add_lhr_star_pimreg (); + break; + case PIM_SPT_INFINITY: + pim_upstream_remove_lhr_star_pimreg (plist); + + if (pimg->spt.plist) + XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); + + if (plist) + pimg->spt.plist = XSTRDUP (MTYPE_PIM_SPT_PLIST_NAME, plist); + break; + } + + 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") +{ + return pim_cmd_spt_switchover (PIM_SPT_INFINITY, NULL); +} + +DEFUN (ip_pim_spt_switchover_infinity_plist, + ip_pim_spt_switchover_infinity_plist_cmd, + "ip pim spt-switchover infinity-and-beyond prefix-list WORD", + IP_STR + PIM_STR + "SPT-Switchover\n" + "Never switch to SPT Tree\n" + "Prefix-List to control which groups to switch\n" + "Prefix-List name\n") +{ + return pim_cmd_spt_switchover (PIM_SPT_INFINITY, argv[5]->arg); +} + +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") +{ + return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL); +} + +DEFUN (no_ip_pim_spt_switchover_infinity_plist, + no_ip_pim_spt_switchover_infinity_plist_cmd, + "no ip pim spt-switchover infinity-and-beyond prefix-list WORD", + NO_STR + IP_STR + PIM_STR + "SPT_Switchover\n" + "Never switch to SPT Tree\n" + "Prefix-List to control which groups to switch\n" + "Prefix-List name\n") +{ + return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL); +} + DEFUN (ip_pim_joinprune_time, ip_pim_joinprune_time_cmd, - "ip pim join-prune-interval <60-600>", + "ip pim join-prune-interval (60-600)", IP_STR "pim multicast routing\n" "Join Prune Send Interval\n" @@ -3373,7 +3869,7 @@ DEFUN (ip_pim_joinprune_time, DEFUN (no_ip_pim_joinprune_time, no_ip_pim_joinprune_time_cmd, - "no ip pim join-prune-interval <60-600>", + "no ip pim join-prune-interval (60-600)", NO_STR IP_STR "pim multicast routing\n" @@ -3386,19 +3882,19 @@ DEFUN (no_ip_pim_joinprune_time, DEFUN (ip_pim_register_suppress, ip_pim_register_suppress_cmd, - "ip pim register-suppress-time <5-60000>", + "ip pim register-suppress-time (5-60000)", IP_STR "pim multicast routing\n" "Register Suppress Timer\n" "Seconds\n") { - qpim_keep_alive_time = atoi (argv[3]->arg); + qpim_register_suppress_time = atoi (argv[3]->arg); return CMD_SUCCESS; } DEFUN (no_ip_pim_register_suppress, no_ip_pim_register_suppress_cmd, - "no ip pim register-suppress-time <5-60000>", + "no ip pim register-suppress-time (5-60000)", NO_STR IP_STR "pim multicast routing\n" @@ -3411,19 +3907,19 @@ DEFUN (no_ip_pim_register_suppress, DEFUN (ip_pim_keep_alive, ip_pim_keep_alive_cmd, - "ip pim keep-alive-timer <31-60000>", + "ip pim keep-alive-timer (31-60000)", IP_STR "pim multicast routing\n" "Keep alive Timer\n" "Seconds\n") { - qpim_rp_keep_alive_time = atoi (argv[4]->arg); + qpim_keep_alive_time = atoi (argv[3]->arg); return CMD_SUCCESS; } DEFUN (no_ip_pim_keep_alive, no_ip_pim_keep_alive_cmd, - "no ip pim keep-alive-timer <31-60000>", + "no ip pim keep-alive-timer (31-60000)", NO_STR IP_STR "pim multicast routing\n" @@ -3436,7 +3932,7 @@ DEFUN (no_ip_pim_keep_alive, DEFUN (ip_pim_packets, ip_pim_packets_cmd, - "ip pim packets <1-100>", + "ip pim packets (1-100)", IP_STR "pim multicast routing\n" "packets to process at one time per fd\n" @@ -3448,7 +3944,7 @@ DEFUN (ip_pim_packets, DEFUN (no_ip_pim_packets, no_ip_pim_packets_cmd, - "no ip pim packets <1-100>", + "no ip pim packets (1-100)", NO_STR IP_STR "pim multicast routing\n" @@ -3459,6 +3955,31 @@ DEFUN (no_ip_pim_packets, 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]", @@ -3471,9 +3992,10 @@ DEFUN (ip_pim_rp, int idx_ipv4 = 3; if (argc == (idx_ipv4 + 1)) - return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); - else return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL); + else + return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); + } DEFUN (ip_pim_rp_prefix_list, @@ -3526,10 +4048,10 @@ DEFUN (no_ip_pim_rp, "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); } @@ -3548,6 +4070,153 @@ DEFUN (no_ip_pim_rp_prefix_list, return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg); } +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 + "pim multicast routing\n" + "Source Specific Multicast\n" + "group range prefix-list filter\n" + "Name of a prefix-list\n") +{ + return pim_ssm_cmd_worker (vty, argv[0]->arg); +} + +DEFUN (no_ip_pim_ssm_prefix_list, + no_ip_pim_ssm_prefix_list_cmd, + "no ip pim ssm prefix-list", + NO_STR + IP_STR + "pim multicast routing\n" + "Source Specific Multicast\n" + "group range prefix-list filter\n") +{ + 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", @@ -3579,7 +4248,7 @@ DEFUN (ip_ssmpingd, int idx_ipv4 = 2; int result; struct in_addr source_addr; - const char *source_str = (argc == idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0"; + const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; result = inet_pton(AF_INET, source_str, &source_addr); if (result <= 0) { @@ -3609,7 +4278,7 @@ DEFUN (no_ip_ssmpingd, int idx_ipv4 = 3; int result; struct in_addr source_addr; - const char *source_str = (argc == idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0"; + const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; result = inet_pton(AF_INET, source_str, &source_addr); if (result <= 0) { @@ -3628,27 +4297,94 @@ DEFUN (no_ip_ssmpingd, return CMD_SUCCESS; } +DEFUN (ip_pim_ecmp, + ip_pim_ecmp_cmd, + "ip pim ecmp", + IP_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_enable = 1; + 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) { struct pim_interface *pim_ifp; + uint8_t need_startup = 0; pim_ifp = ifp->info; - if (!pim_ifp) { - pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */); - if (!pim_ifp) { - vty_out(vty, "Could not enable IGMP on interface %s%s", + if (!pim_ifp) + { + pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */); + if (!pim_ifp) + { + vty_out(vty, "Could not enable IGMP on interface %s%s", ifp->name, VTY_NEWLINE); - return CMD_WARNING; + return CMD_WARNING; + } + need_startup = 1; + } + else + { + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) + { + PIM_IF_DO_IGMP(pim_ifp->options); + need_startup = 1; + } } - } - else { - PIM_IF_DO_IGMP(pim_ifp->options); - } - pim_if_addr_add_all(ifp); - pim_if_membership_refresh(ifp); + /* 'ip igmp' executed multiple times, with need_startup + avoid multiple if add all and membership refresh */ + if (need_startup) + { + pim_if_addr_add_all(ifp); + pim_if_membership_refresh(ifp); + } return CMD_SUCCESS; } @@ -4014,22 +4750,37 @@ DEFUN (interface_ip_igmp_version, "IGMP version number\n") { VTY_DECLVAR_CONTEXT(interface,ifp); - struct pim_interface *pim_ifp; - int igmp_version; + struct pim_interface *pim_ifp = NULL; + int igmp_version, old_version = 0; int ret; pim_ifp = ifp->info; - if (!pim_ifp) { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } + if (!pim_ifp) + { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } igmp_version = atoi(argv[3]->arg); + old_version = pim_ifp->igmp_version; pim_ifp->igmp_version = igmp_version; + //Check if IGMP is Enabled otherwise, enable on interface + if (!PIM_IF_TEST_IGMP (pim_ifp->options)) + { + PIM_IF_DO_IGMP(pim_ifp->options); + pim_if_addr_add_all(ifp); + pim_if_membership_refresh(ifp); + old_version = igmp_version; //avoid refreshing membership again. + } + /* Current and new version is different refresh existing + membership. Going from 3 -> 2 or 2 -> 3. */ + if (old_version != igmp_version) + pim_if_membership_refresh(ifp); + return CMD_SUCCESS; } @@ -4242,7 +4993,7 @@ DEFUN (interface_no_ip_pim_drprio, } 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; @@ -4256,14 +5007,12 @@ pim_cmd_interface_add (struct interface *ifp, enum pim_interface_type itype) 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 @@ -4272,11 +5021,12 @@ DEFUN (interface_ip_pim_ssm, { 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; } @@ -4288,7 +5038,7 @@ DEFUN (interface_ip_pim_sm, 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; } @@ -4324,7 +5074,7 @@ pim_cmd_interface_delete (struct interface *ifp) 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 @@ -4377,7 +5127,7 @@ DEFUN (interface_ip_mroute, 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); @@ -4424,7 +5174,7 @@ DEFUN (interface_ip_mroute_source, 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); @@ -4475,7 +5225,7 @@ DEFUN (interface_no_ip_mroute, 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); @@ -4523,7 +5273,7 @@ DEFUN (interface_no_ip_mroute_source, 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); @@ -4577,7 +5327,7 @@ DEFUN (interface_ip_pim_hello, pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10); - if (argc == idx_hold) + if (argc == idx_hold + 1) pim_ifp->pim_default_holdtime = strtol(argv[idx_hold]->arg, NULL, 10); return CMD_SUCCESS; @@ -5452,7 +6202,7 @@ DEFUN (no_ip_msdp_mesh_group_source, "mesh group source\n" "mesh group local address\n") { - if (argc == 6) + if (argc == 7) return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg); else return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg); @@ -5952,13 +6702,16 @@ DEFUN (show_ip_msdp_sa_sg, "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); @@ -5979,18 +6732,31 @@ void pim_cmd_init() 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, &ip_pim_spt_switchover_infinity_plist_cmd); + install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd); + install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_plist_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); @@ -6029,6 +6795,7 @@ void pim_cmd_init() install_element (VIEW_NODE, &show_ip_pim_assert_internal_cmd); install_element (VIEW_NODE, &show_ip_pim_assert_metric_cmd); install_element (VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd); + install_element (VIEW_NODE, &show_ip_pim_interface_traffic_cmd); install_element (VIEW_NODE, &show_ip_pim_interface_cmd); install_element (VIEW_NODE, &show_ip_pim_join_cmd); install_element (VIEW_NODE, &show_ip_pim_local_membership_cmd); @@ -6046,11 +6813,14 @@ void pim_cmd_init() 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 (ENABLE_NODE, &clear_ip_mroute_cmd); install_element (ENABLE_NODE, &clear_ip_pim_interfaces_cmd); + install_element (ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); install_element (ENABLE_NODE, &clear_ip_pim_oil_cmd); install_element (ENABLE_NODE, &debug_igmp_cmd); @@ -6136,6 +6906,8 @@ void pim_cmd_init() 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); }