]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_cmd.c
Merge pull request #3775 from pguibert6WIND/ospf_missing_interface_handling_2
[mirror_frr.git] / pimd / pim_cmd.c
index 77ea314d54d5bf154cf30699681fefb8ed3ae84f..d71b4bf640d0b0023557a18f756aff52844b5767 100644 (file)
@@ -62,6 +62,7 @@
 #include "pim_bfd.h"
 #include "pim_vxlan.h"
 #include "bfd.h"
+#include "pim_bsm.h"
 
 #ifndef VTYSH_EXTRACT_PL
 #include "pimd/pim_cmd_clippy.c"
@@ -657,6 +658,7 @@ static void igmp_show_interfaces_single(struct pim_instance *pim,
        long oqpi_msec; /* Other Querier Present Interval */
        long qri_msec;
        time_t now;
+       int lmqc;
 
        json_object *json = NULL;
        json_object *json_row = NULL;
@@ -701,8 +703,8 @@ static void igmp_show_interfaces_single(struct pim_instance *pim,
                                pim_ifp->igmp_query_max_response_time_dsec);
 
                        lmqt_msec = PIM_IGMP_LMQT_MSEC(
-                               pim_ifp->igmp_query_max_response_time_dsec,
-                               igmp->querier_robustness_variable);
+                               pim_ifp->igmp_specific_query_max_response_time_dsec,
+                               pim_ifp->igmp_last_member_query_count);
 
                        ohpi_msec =
                                PIM_IGMP_OHPI_DSEC(
@@ -718,6 +720,7 @@ static void igmp_show_interfaces_single(struct pim_instance *pim,
                                        pim_ifp->pim_sock_fd);
                        else
                                mloop = 0;
+                       lmqc = pim_ifp->igmp_last_member_query_count;
 
                        if (uj) {
                                json_row = json_object_new_object();
@@ -742,6 +745,9 @@ static void igmp_show_interfaces_single(struct pim_instance *pim,
                                        json_row,
                                        "timerGroupMembershipIntervalMsec",
                                        gmi_msec);
+                               json_object_int_add(json_row,
+                                                   "lastMemberQueryCount",
+                                                   lmqc);
                                json_object_int_add(json_row,
                                                    "timerLastMemberQueryMsec",
                                                    lmqt_msec);
@@ -808,6 +814,9 @@ static void igmp_show_interfaces_single(struct pim_instance *pim,
                                vty_out(vty,
                                        "Group Membership Interval      : %lis\n",
                                        gmi_msec / 1000);
+                               vty_out(vty,
+                                       "Last Member Query Count        : %d\n",
+                                       lmqc);
                                vty_out(vty,
                                        "Last Member Query Time         : %lis\n",
                                        lmqt_msec / 1000);
@@ -1207,6 +1216,8 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
                        print_header = 1;
                        for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
                                                  up)) {
+                               if (!up->rpf.source_nexthop.interface)
+                                       continue;
 
                                if (strcmp(ifp->name,
                                           up->rpf.source_nexthop
@@ -1475,13 +1486,14 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
                json = json_object_new_object();
        else {
                vty_out(vty, "\n");
-               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+               vty_out(vty, "%-16s%-17s%-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", "",
+                       "  ASSERT", "  BSM");
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
                        "       Rx/Tx", "       Rx/Tx", "      Rx/Tx",
-                       "     Rx/Tx", "    Rx/Tx", "   Rx/Tx");
+                       "      Rx/Tx", "     Rx/Tx", "    Rx/Tx",
+                       "   Rx/Tx");
                vty_out(vty,
                        "---------------------------------------------------------------------------------------------------------------\n");
        }
@@ -1516,12 +1528,15 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
                        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);
-
+                                       pim_ifp->pim_ifstat_assert_send);
+                       json_object_int_add(json_row, "bsmRx",
+                                       pim_ifp->pim_ifstat_bsm_rx);
+                       json_object_int_add(json_row, "bsmTx",
+                                       pim_ifp->pim_ifstat_bsm_tx);
                        json_object_object_add(json, ifp->name, json_row);
                } else {
                        vty_out(vty,
-                               "%-16s %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 %7" PRIu64 "/%-7" PRIu64 "\n",
                                ifp->name, pim_ifp->pim_ifstat_hello_recv,
                                pim_ifp->pim_ifstat_hello_sent,
                                pim_ifp->pim_ifstat_join_recv,
@@ -1533,7 +1548,9 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
                                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);
+                               pim_ifp->pim_ifstat_assert_send,
+                               pim_ifp->pim_ifstat_bsm_rx,
+                               pim_ifp->pim_ifstat_bsm_tx);
                }
        }
        if (uj) {
@@ -1557,14 +1574,15 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
                json = json_object_new_object();
        else {
                vty_out(vty, "\n");
-               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
                        "Interface", "    HELLO", "    JOIN", "   PRUNE",
-                       "   REGISTER", "  REGISTER-STOP", "  ASSERT");
-               vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
+                       "   REGISTER", "  REGISTER-STOP", "  ASSERT",
+                       "    BSM");
+               vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
                        "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
-                       "     Rx/Tx", "    Rx/Tx");
+                       "     Rx/Tx", "    Rx/Tx", "    Rx/Tx");
                vty_out(vty,
-                       "---------------------------------------------------------------------------------------------------------------------\n");
+                       "-------------------------------------------------------------------------------------------------------------------------------\n");
        }
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -1603,11 +1621,15 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
                                            pim_ifp->pim_ifstat_assert_recv);
                        json_object_int_add(json_row, "assertTx",
                                            pim_ifp->pim_ifstat_assert_send);
+                       json_object_int_add(json_row, "bsmRx",
+                                           pim_ifp->pim_ifstat_bsm_rx);
+                       json_object_int_add(json_row, "bsmTx",
+                                           pim_ifp->pim_ifstat_bsm_tx);
 
                        json_object_object_add(json, ifp->name, json_row);
                } else {
                        vty_out(vty,
-                               "%-16s %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 %7" PRIu64 "/%-7" PRIu64 "\n",
                                ifp->name, pim_ifp->pim_ifstat_hello_recv,
                                pim_ifp->pim_ifstat_hello_sent,
                                pim_ifp->pim_ifstat_join_recv,
@@ -1619,7 +1641,9 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
                                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);
+                               pim_ifp->pim_ifstat_assert_send,
+                               pim_ifp->pim_ifstat_bsm_rx,
+                               pim_ifp->pim_ifstat_bsm_tx);
                }
        }
        if (uj) {
@@ -1985,9 +2009,9 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
 
                if (ifp_in)
-                       strcpy(in_ifname, ifp_in->name);
+                       strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
                else
-                       strcpy(in_ifname, "<iif?>");
+                       strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
 
                if (src_or_group) {
                        if (strcmp(src_or_group, src_str)
@@ -2069,9 +2093,9 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                                now - c_oil->oif_creation[oif_vif_index]);
 
                        if (ifp_out)
-                               strcpy(out_ifname, ifp_out->name);
+                               strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
                        else
-                               strcpy(out_ifname, "<oif?>");
+                               strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
 
                        if (uj) {
                                json_ifp_out = json_object_new_object();
@@ -2093,7 +2117,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                        } else {
                                if (first_oif) {
                                        first_oif = 0;
-                                       vty_out(vty, "%s(%c%c%c%c%c)", 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'
@@ -2106,16 +2130,12 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                                                 & PIM_OIF_FLAG_PROTO_VXLAN)
                                                        ? 'V'
                                                        : ' ',
-                                               (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(%c%c%c%c%c)",
+                                       vty_out(vty, ", %s(%c%c%c%c)",
                                                out_ifname,
                                                (c_oil->oif_flags[oif_vif_index]
                                                 & PIM_OIF_FLAG_PROTO_IGMP)
@@ -2129,10 +2149,6 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                                                 & PIM_OIF_FLAG_PROTO_VXLAN)
                                                        ? 'V'
                                                        : ' ',
-                                               (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)
                                                        ? '*'
@@ -2311,41 +2327,76 @@ static void json_object_pim_upstream_add(json_object *json,
        /* XXX: need to print ths flag in the plain text display as well */
        if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
                json_object_boolean_true_add(json, "sourceMsdp");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
+               json_object_boolean_true_add(json, "sendSGRptPrune");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
+               json_object_boolean_true_add(json, "lastHopRouter");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
+               json_object_boolean_true_add(json, "disableKATExpiry");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
+               json_object_boolean_true_add(json, "staticIncomingInterface");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
+               json_object_boolean_true_add(json,
+                                            "allowIncomingInterfaceinOil");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
+               json_object_boolean_true_add(json, "noPimRegistrationData");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
+               json_object_boolean_true_add(json, "forcePimRegistration");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
+               json_object_boolean_true_add(json, "sourceVxlanOrigination");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
+               json_object_boolean_true_add(json, "sourceVxlanTermination");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
+               json_object_boolean_true_add(json, "mlagVxlan");
+
+       if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
+               json_object_boolean_true_add(json,
+                                            "mlagNonDesignatedForwarder");
 }
 
 static const char *
 pim_upstream_state2brief_str(enum pim_upstream_state join_state,
-                            char *state_str)
+                            char *state_str, size_t state_str_len)
 {
        switch (join_state) {
        case PIM_UPSTREAM_NOTJOINED:
-               strcpy(state_str, "NotJ");
+               strlcpy(state_str, "NotJ", state_str_len);
                break;
        case PIM_UPSTREAM_JOINED:
-               strcpy(state_str, "J");
+               strlcpy(state_str, "J", state_str_len);
                break;
        default:
-               strcpy(state_str, "Unk");
+               strlcpy(state_str, "Unk", state_str_len);
        }
        return state_str;
 }
 
 static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
-                                          char *state_str)
+                                          char *state_str, size_t state_str_len)
 {
        switch (reg_state) {
        case PIM_REG_NOINFO:
-               strcpy(state_str, "RegNI");
+               strlcpy(state_str, "RegNI", state_str_len);
                break;
        case PIM_REG_JOIN:
-               strcpy(state_str, "RegJ");
+               strlcpy(state_str, "RegJ", state_str_len);
                break;
        case PIM_REG_JOIN_PENDING:
        case PIM_REG_PRUNE:
-               strcpy(state_str, "RegP");
+               strlcpy(state_str, "RegP", state_str_len);
                break;
        default:
-               strcpy(state_str, "Unk");
+               strlcpy(state_str, "Unk", state_str_len);
        }
        return state_str;
 }
@@ -2413,13 +2464,13 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                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);
+               pim_upstream_state2brief_str(up->join_state, state_str, sizeof(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));
+                               pim_reg_state2brief_str(up->reg_state, tmp_str,
+                                                       sizeof(tmp_str)));
                }
 
                if (uj) {
@@ -2470,7 +2521,7 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                                pim_upstream_state2str(up->join_state));
                        json_object_string_add(
                                json_row, "regState",
-                               pim_reg_state2str(up->reg_state, state_str));
+                               pim_reg_state2str(up->reg_state, state_str, sizeof(state_str)));
                        json_object_string_add(json_row, "upTime", uptime);
                        json_object_string_add(json_row, "joinTimer",
                                               join_timer);
@@ -2851,6 +2902,415 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
        hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
 }
 
+/* Display the bsm database details */
+static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+       struct listnode *bsmnode;
+       int count = 0;
+       int fragment = 1;
+       struct bsm_info *bsm;
+       json_object *json = NULL;
+       json_object *json_group = NULL;
+       json_object *json_row = NULL;
+
+       count = pim->global_scope.bsm_list->count;
+
+       if (uj) {
+               json = json_object_new_object();
+               json_object_int_add(json, "Number of the fragments", count);
+       } else {
+               vty_out(vty, "Scope Zone: Global\n");
+               vty_out(vty, "Number of the fragments: %d\n", count);
+               vty_out(vty, "\n");
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(pim->global_scope.bsm_list, bsmnode, bsm)) {
+               char grp_str[INET_ADDRSTRLEN];
+               char rp_str[INET_ADDRSTRLEN];
+               char bsr_str[INET_ADDRSTRLEN];
+               struct bsmmsg_grpinfo *group;
+               struct bsmmsg_rpinfo *rpaddr;
+               struct prefix grp;
+               struct bsm_hdr *hdr;
+               uint32_t offset = 0;
+               uint8_t *buf;
+               uint32_t len = 0;
+               uint32_t frag_rp_cnt = 0;
+
+               buf = bsm->bsm;
+               len = bsm->size;
+
+               /* skip pim header */
+               buf += PIM_MSG_HEADER_LEN;
+               len -= PIM_MSG_HEADER_LEN;
+
+               hdr = (struct bsm_hdr *)buf;
+
+               /* BSM starts with bsr header */
+               buf += sizeof(struct bsm_hdr);
+               len -= sizeof(struct bsm_hdr);
+
+               pim_inet4_dump("<BSR Address?>", hdr->bsr_addr.addr, bsr_str,
+                              sizeof(bsr_str));
+
+
+               if (uj) {
+                       json_object_string_add(json, "BSR address", bsr_str);
+                       json_object_int_add(json, "BSR priority",
+                                           hdr->bsr_prio);
+                       json_object_int_add(json, "Hashmask Length",
+                                           hdr->hm_len);
+                       json_object_int_add(json, "Fragment Tag",
+                                           ntohs(hdr->frag_tag));
+               } else {
+                       vty_out(vty, "BSM Fragment : %d\n", fragment);
+                       vty_out(vty, "------------------\n");
+                       vty_out(vty, "%-15s %-15s %-15s %-15s\n", "BSR-Address",
+                               "BSR-Priority", "Hashmask-len", "Fragment-Tag");
+                       vty_out(vty, "%-15s %-15d %-15d %-15d\n", bsr_str,
+                               hdr->bsr_prio, hdr->hm_len,
+                               ntohs(hdr->frag_tag));
+               }
+
+               vty_out(vty, "\n");
+
+               while (offset < len) {
+                       group = (struct bsmmsg_grpinfo *)buf;
+
+                       if (group->group.family == PIM_MSG_ADDRESS_FAMILY_IPV4)
+                               grp.family = AF_INET;
+
+                       grp.prefixlen = group->group.mask;
+                       grp.u.prefix4.s_addr = group->group.addr.s_addr;
+
+                       prefix2str(&grp, grp_str, sizeof(grp_str));
+
+                       buf += sizeof(struct bsmmsg_grpinfo);
+                       offset += sizeof(struct bsmmsg_grpinfo);
+
+                       if (uj) {
+                               json_object_object_get_ex(json, grp_str,
+                                                         &json_group);
+                               if (!json_group) {
+                                       json_group = json_object_new_object();
+                                       json_object_int_add(json_group,
+                                                           "Rp Count",
+                                                           group->rp_count);
+                                       json_object_int_add(
+                                               json_group, "Fragment Rp count",
+                                               group->frag_rp_count);
+                                       json_object_object_add(json, grp_str,
+                                                              json_group);
+                               }
+                       } else {
+                               vty_out(vty, "Group : %s\n", grp_str);
+                               vty_out(vty, "-------------------\n");
+                               vty_out(vty, "Rp Count:%d\n", group->rp_count);
+                               vty_out(vty, "Fragment Rp Count : %d\n",
+                                       group->frag_rp_count);
+                       }
+
+                       frag_rp_cnt = group->frag_rp_count;
+
+                       if (!frag_rp_cnt)
+                               continue;
+
+                       if (!uj)
+                               vty_out(vty,
+                                       "RpAddress     HoldTime     Priority\n");
+
+                       while (frag_rp_cnt--) {
+                               rpaddr = (struct bsmmsg_rpinfo *)buf;
+
+                               buf += sizeof(struct bsmmsg_rpinfo);
+                               offset += sizeof(struct bsmmsg_rpinfo);
+
+                               pim_inet4_dump("<Rp addr?>",
+                                              rpaddr->rpaddr.addr, rp_str,
+                                              sizeof(rp_str));
+
+                               if (uj) {
+                                       json_row = json_object_new_object();
+                                       json_object_string_add(
+                                               json_row, "Rp Address", rp_str);
+                                       json_object_int_add(
+                                               json_row, "Rp HoldTime",
+                                               ntohs(rpaddr->rp_holdtime));
+                                       json_object_int_add(json_row,
+                                                           "Rp Priority",
+                                                           rpaddr->rp_pri);
+                                       json_object_object_add(
+                                               json_group, rp_str, json_row);
+                               } else {
+                                       vty_out(vty, "%-15s %-12d %d\n", rp_str,
+                                               ntohs(rpaddr->rp_holdtime),
+                                               rpaddr->rp_pri);
+                               }
+                       }
+                       vty_out(vty, "\n");
+               }
+
+               fragment++;
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
+/*Display the group-rp mappings */
+static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
+                                           struct vty *vty, bool uj)
+{
+       struct bsgrp_node *bsgrp;
+       struct listnode *rpnode;
+       struct bsm_rpinfo *bsm_rp;
+       struct route_node *rn;
+       char bsr_str[INET_ADDRSTRLEN];
+       json_object *json = NULL;
+       json_object *json_group = NULL;
+       json_object *json_row = NULL;
+
+       if (pim->global_scope.current_bsr.s_addr == INADDR_ANY)
+               strlcpy(bsr_str, "0.0.0.0", sizeof(bsr_str));
+
+       else
+               pim_inet4_dump("<bsr?>", pim->global_scope.current_bsr, bsr_str,
+                              sizeof(bsr_str));
+
+       if (uj) {
+               json = json_object_new_object();
+               json_object_string_add(json, "BSR Address", bsr_str);
+       } else {
+               vty_out(vty, "BSR Address  %s\n", bsr_str);
+       }
+
+       for (rn = route_top(pim->global_scope.bsrp_table); rn;
+            rn = route_next(rn)) {
+               bsgrp = (struct bsgrp_node *)rn->info;
+
+               if (!bsgrp)
+                       continue;
+
+               char grp_str[INET_ADDRSTRLEN];
+
+               prefix2str(&bsgrp->group, grp_str, sizeof(grp_str));
+
+               if (uj) {
+                       json_object_object_get_ex(json, grp_str, &json_group);
+                       if (!json_group) {
+                               json_group = json_object_new_object();
+                               json_object_object_add(json, grp_str,
+                                                      json_group);
+                       }
+               } else {
+                       vty_out(vty, "Group Address %s\n", grp_str);
+                       vty_out(vty, "--------------------------\n");
+                       vty_out(vty, "%-15s %-15s %-15s %-15s\n", "Rp Address",
+                               "priority", "Holdtime", "Hash");
+
+                       vty_out(vty, "(ACTIVE)\n");
+               }
+
+               if (bsgrp->bsrp_list) {
+                       for (ALL_LIST_ELEMENTS_RO(bsgrp->bsrp_list, rpnode,
+                                                 bsm_rp)) {
+                               char rp_str[INET_ADDRSTRLEN];
+
+                               pim_inet4_dump("<Rp Address?>",
+                                              bsm_rp->rp_address, rp_str,
+                                              sizeof(rp_str));
+
+                               if (uj) {
+                                       json_row = json_object_new_object();
+                                       json_object_string_add(
+                                               json_row, "Rp Address", rp_str);
+                                       json_object_int_add(
+                                               json_row, "Rp HoldTime",
+                                               bsm_rp->rp_holdtime);
+                                       json_object_int_add(json_row,
+                                                           "Rp Priority",
+                                                           bsm_rp->rp_prio);
+                                       json_object_int_add(json_row,
+                                                           "Hash Val",
+                                                           bsm_rp->hash);
+                                       json_object_object_add(
+                                               json_group, rp_str, json_row);
+
+                               } else {
+                                       vty_out(vty,
+                                               "%-15s %-15u %-15u %-15u\n",
+                                               rp_str, bsm_rp->rp_prio,
+                                               bsm_rp->rp_holdtime,
+                                               bsm_rp->hash);
+                               }
+                       }
+                       if (!bsgrp->bsrp_list->count && !uj)
+                               vty_out(vty, "Active List is empty.\n");
+               }
+
+               if (uj) {
+                       json_object_int_add(json_group, "Pending RP count",
+                                           bsgrp->pend_rp_cnt);
+               } else {
+                       vty_out(vty, "(PENDING)\n");
+                       vty_out(vty, "Pending RP count :%d\n",
+                               bsgrp->pend_rp_cnt);
+                       if (bsgrp->pend_rp_cnt)
+                               vty_out(vty, "%-15s %-15s %-15s %-15s\n",
+                                       "Rp Address", "priority", "Holdtime",
+                                       "Hash");
+               }
+
+               if (bsgrp->partial_bsrp_list) {
+                       for (ALL_LIST_ELEMENTS_RO(bsgrp->partial_bsrp_list,
+                                                 rpnode, bsm_rp)) {
+                               char rp_str[INET_ADDRSTRLEN];
+
+                               pim_inet4_dump("<Rp Addr?>", bsm_rp->rp_address,
+                                              rp_str, sizeof(rp_str));
+
+                               if (uj) {
+                                       json_row = json_object_new_object();
+                                       json_object_string_add(
+                                               json_row, "Rp Address", rp_str);
+                                       json_object_int_add(
+                                               json_row, "Rp HoldTime",
+                                               bsm_rp->rp_holdtime);
+                                       json_object_int_add(json_row,
+                                                           "Rp Priority",
+                                                           bsm_rp->rp_prio);
+                                       json_object_int_add(json_row,
+                                                           "Hash Val",
+                                                           bsm_rp->hash);
+                                       json_object_object_add(
+                                               json_group, rp_str, json_row);
+                               } else {
+                                       vty_out(vty,
+                                               "%-15s %-15u %-15u %-15u\n",
+                                               rp_str, bsm_rp->rp_prio,
+                                               bsm_rp->rp_holdtime,
+                                               bsm_rp->hash);
+                               }
+                       }
+                       if (!bsgrp->partial_bsrp_list->count && !uj)
+                               vty_out(vty, "Partial List is empty\n");
+               }
+
+               if (!uj)
+                       vty_out(vty, "\n");
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
+/* pim statistics - just adding only bsm related now.
+ * We can continue to add all pim related stats here.
+ */
+static void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
+                               const char *ifname, bool uj)
+{
+       json_object *json = NULL;
+       struct interface *ifp;
+
+       if (uj) {
+               json = json_object_new_object();
+               json_object_int_add(json, "Number of Received BSMs",
+                                   pim->bsm_rcvd);
+               json_object_int_add(json, "Number of Forwared BSMs",
+                                   pim->bsm_sent);
+               json_object_int_add(json, "Number of Dropped BSMs",
+                                   pim->bsm_dropped);
+       } else {
+               vty_out(vty, "BSM Statistics :\n");
+               vty_out(vty, "----------------\n");
+               vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
+                       pim->bsm_rcvd);
+               vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
+                       pim->bsm_sent);
+               vty_out(vty, "Number of Dropped BSMs  : %" PRIu64 "\n",
+                       pim->bsm_dropped);
+       }
+
+       vty_out(vty, "\n");
+
+       /* scan interfaces */
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp = ifp->info;
+
+               if (ifname && strcmp(ifname, ifp->name))
+                       continue;
+
+               if (!pim_ifp)
+                       continue;
+
+               if (!uj) {
+                       vty_out(vty, "Interface : %s\n", ifp->name);
+                       vty_out(vty, "-------------------\n");
+                       vty_out(vty,
+                               "Number of BSMs dropped due to config miss : %u\n",
+                               pim_ifp->pim_ifstat_bsm_cfg_miss);
+                       vty_out(vty, "Number of unicast BSMs dropped : %u\n",
+                               pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
+                       vty_out(vty,
+                               "Number of BSMs dropped due to invalid scope zone : %u\n",
+                               pim_ifp->pim_ifstat_bsm_invalid_sz);
+               } else {
+
+                       json_object *json_row = NULL;
+
+                       json_row = json_object_new_object();
+
+                       json_object_string_add(json_row, "If Name", ifp->name);
+                       json_object_int_add(
+                               json_row,
+                               "Number of BSMs dropped due to config miss",
+                               pim_ifp->pim_ifstat_bsm_cfg_miss);
+                       json_object_int_add(
+                               json_row, "Number of unicast BSMs dropped",
+                               pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
+                       json_object_int_add(json_row,
+                                           "Number of BSMs dropped due to invalid scope zone",
+                                           pim_ifp->pim_ifstat_bsm_invalid_sz);
+                       json_object_object_add(json, ifp->name, json_row);
+               }
+               vty_out(vty, "\n");
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
+static void clear_pim_statistics(struct pim_instance *pim)
+{
+       struct interface *ifp;
+
+       pim->bsm_rcvd = 0;
+       pim->bsm_sent = 0;
+       pim->bsm_dropped = 0;
+
+       /* scan interfaces */
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp = ifp->info;
+
+               if (!pim_ifp)
+                       continue;
+
+               pim_ifp->pim_ifstat_bsm_cfg_miss = 0;
+               pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0;
+               pim_ifp->pim_ifstat_bsm_invalid_sz = 0;
+       }
+}
+
 static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
 {
        struct interface *ifp;
@@ -3170,6 +3630,82 @@ static void igmp_show_source_retransmission(struct pim_instance *pim,
        }                         /* scan interfaces */
 }
 
+static void pim_show_bsr(struct pim_instance *pim,
+                        struct vty *vty,
+                        bool uj)
+{
+       char uptime[10];
+       char last_bsm_seen[10];
+       time_t now;
+       char bsr_state[20];
+       char bsr_str[PREFIX_STRLEN];
+       json_object *json = NULL;
+
+       vty_out(vty, "PIMv2 Bootstrap information\n");
+
+       if (pim->global_scope.current_bsr.s_addr == INADDR_ANY) {
+               strlcpy(bsr_str, "0.0.0.0", sizeof(bsr_str));
+               pim_time_uptime(uptime, sizeof(uptime),
+                               pim->global_scope.current_bsr_first_ts);
+               pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
+                               pim->global_scope.current_bsr_last_ts);
+       }
+
+       else {
+               pim_inet4_dump("<bsr?>", pim->global_scope.current_bsr,
+                              bsr_str, sizeof(bsr_str));
+               now = pim_time_monotonic_sec();
+               pim_time_uptime(uptime, sizeof(uptime),
+                               (now - pim->global_scope.current_bsr_first_ts));
+               pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
+                               now - pim->global_scope.current_bsr_last_ts);
+       }
+
+       switch (pim->global_scope.state) {
+       case NO_INFO:
+               strlcpy(bsr_state, "NO_INFO", sizeof(bsr_state));
+               break;
+       case ACCEPT_ANY:
+               strlcpy(bsr_state, "ACCEPT_ANY", sizeof(bsr_state));
+               break;
+       case ACCEPT_PREFERRED:
+               strlcpy(bsr_state, "ACCEPT_PREFERRED", sizeof(bsr_state));
+               break;
+       default:
+               strlcpy(bsr_state, "", sizeof(bsr_state));
+       }
+
+       if (uj) {
+               json = json_object_new_object();
+               json_object_string_add(json, "bsr", bsr_str);
+               json_object_int_add(json, "priority",
+                                   pim->global_scope.current_bsr_prio);
+               json_object_int_add(json, "fragment_tag",
+                                   pim->global_scope.bsm_frag_tag);
+               json_object_string_add(json, "state", bsr_state);
+               json_object_string_add(json, "upTime", uptime);
+               json_object_string_add(json, "last_bsm_seen", last_bsm_seen);
+       }
+
+       else {
+               vty_out(vty, "Current preferred BSR address: %s\n", bsr_str);
+               vty_out(vty,
+                       "Priority        Fragment-Tag       State           UpTime\n");
+               vty_out(vty, "  %-12d    %-12d    %-13s    %7s\n",
+                       pim->global_scope.current_bsr_prio,
+                       pim->global_scope.bsm_frag_tag,
+                       bsr_state,
+                       uptime);
+               vty_out(vty, "Last BSM seen: %s\n", last_bsm_seen);
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
 static void clear_igmp_interfaces(struct pim_instance *pim)
 {
        struct interface *ifp;
@@ -3245,44 +3781,70 @@ DEFUN (clear_ip_igmp_interfaces,
        return CMD_SUCCESS;
 }
 
-static void mroute_add_all(struct pim_instance *pim)
+DEFUN (clear_ip_pim_statistics,
+       clear_ip_pim_statistics_cmd,
+       "clear ip pim statistics [vrf NAME]",
+       CLEAR_STR
+       IP_STR
+       CLEAR_IP_PIM_STR
+       VRF_CMD_HELP_STR
+       "Reset PIM statistics\n")
 {
-       struct listnode *node;
-       struct channel_oil *c_oil;
+       int idx = 2;
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
 
-       for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
-               if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) {
-                       /* just log warning */
-                       char source_str[INET_ADDRSTRLEN];
-                       char group_str[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
-                                      source_str, sizeof(source_str));
-                       pim_inet4_dump("<group?>", 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);
-               }
-       }
+       if (!vrf)
+               return CMD_WARNING;
+
+       clear_pim_statistics(vrf->info);
+       return CMD_SUCCESS;
 }
 
-static void mroute_del_all(struct pim_instance *pim)
+static void clear_mroute(struct pim_instance *pim)
 {
-       struct listnode *node;
-       struct channel_oil *c_oil;
+       struct pim_upstream *up;
+       struct interface *ifp;
 
-       for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
-               if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) {
-                       /* just log warning */
-                       char source_str[INET_ADDRSTRLEN];
-                       char group_str[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
-                                      source_str, sizeof(source_str));
-                       pim_inet4_dump("<group?>", 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);
+       /* scan interfaces */
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp = ifp->info;
+               struct listnode *sock_node;
+               struct igmp_sock *igmp;
+               struct pim_ifchannel *ch;
+
+               if (!pim_ifp)
+                       continue;
+
+               /* deleting all ifchannels */
+               while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
+                       ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
+
+                       pim_ifchannel_delete(ch);
+               }
+
+               /* clean up all igmp groups */
+               /* scan igmp sockets */
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
+                                       igmp)) {
+
+                       struct igmp_group *grp;
+
+                       if (igmp->igmp_group_list) {
+                               while (igmp->igmp_group_list->count) {
+                                       grp = listnode_head(
+                                               igmp->igmp_group_list);
+                                       igmp_group_delete(grp);
+                               }
+                       }
+
+               }
+       }
+
+       /* clean up all upstreams*/
+       if (pim->upstream_list) {
+               while (pim->upstream_list->count) {
+                       up = listnode_head(pim->upstream_list);
+                       pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
                }
        }
 }
@@ -3301,8 +3863,7 @@ DEFUN (clear_ip_mroute,
        if (!vrf)
                return CMD_WARNING;
 
-       mroute_del_all(vrf->info);
-       mroute_add_all(vrf->info);
+       clear_mroute(vrf->info);
 
        return CMD_SUCCESS;
 }
@@ -3363,6 +3924,8 @@ DEFUN (clear_ip_pim_interface_traffic,
                pim_ifp->pim_ifstat_reg_stop_send = 0;
                pim_ifp->pim_ifstat_assert_recv = 0;
                pim_ifp->pim_ifstat_assert_send = 0;
+               pim_ifp->pim_ifstat_bsm_rx = 0;
+               pim_ifp->pim_ifstat_bsm_tx = 0;
        }
 
        return CMD_SUCCESS;
@@ -4422,6 +4985,76 @@ DEFUN (show_ip_pim_interface_traffic,
        return CMD_SUCCESS;
 }
 
+DEFUN (show_ip_pim_bsm_db,
+       show_ip_pim_bsm_db_cmd,
+       "show ip pim bsm-database [vrf NAME] [json]",
+       SHOW_STR
+       IP_STR
+       PIM_STR
+       VRF_CMD_HELP_STR
+       "PIM cached bsm packets information\n"
+       JSON_STR)
+{
+       int idx = 2;
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       bool uj = use_json(argc, argv);
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       pim_show_bsm_db(vrf->info, vty, uj);
+       return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_bsrp,
+       show_ip_pim_bsrp_cmd,
+       "show ip pim bsrp-info [vrf NAME] [json]",
+       SHOW_STR
+       IP_STR
+       PIM_STR
+       VRF_CMD_HELP_STR
+       "PIM cached group-rp mappings information\n"
+       JSON_STR)
+{
+       int idx = 2;
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       bool uj = use_json(argc, argv);
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       pim_show_group_rp_mappings_info(vrf->info, vty, uj);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_pim_statistics,
+       show_ip_pim_statistics_cmd,
+       "show ip pim [vrf NAME] statistics  [interface WORD] [json]",
+       SHOW_STR
+       IP_STR
+       PIM_STR
+       VRF_CMD_HELP_STR
+       "PIM statistics\n"
+       "interface\n"
+       "PIM interface\n"
+       JSON_STR)
+{
+       int idx = 2;
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       bool uj = use_json(argc, argv);
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       if (argv_find(argv, argc, "WORD", &idx))
+               pim_show_statistics(vrf->info, vty, argv[idx]->arg, uj);
+       else
+               pim_show_statistics(vrf->info, vty, NULL, uj);
+
+       return CMD_SUCCESS;
+}
+
 static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
 {
        struct interface *ifp;
@@ -4609,9 +5242,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
                ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
 
                if (ifp_in)
-                       strcpy(in_ifname, ifp_in->name);
+                       strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
                else
-                       strcpy(in_ifname, "<iif?>");
+                       strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
 
                if (uj) {
 
@@ -4666,9 +5299,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
                        found_oif = 1;
 
                        if (ifp_out)
-                               strcpy(out_ifname, ifp_out->name);
+                               strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
                        else
-                               strcpy(out_ifname, "<oif?>");
+                               strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
 
                        if (uj) {
                                json_ifp_out = json_object_new_object();
@@ -4692,11 +5325,6 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
                                        json_object_boolean_true_add(
                                                json_ifp_out, "protocolVxlan");
 
-                               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(
@@ -4726,27 +5354,22 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
                        } else {
                                if (c_oil->oif_flags[oif_vif_index]
                                    & PIM_OIF_FLAG_PROTO_PIM) {
-                                       strcpy(proto, "PIM");
+                                       strlcpy(proto, "PIM", sizeof(proto));
                                }
 
                                if (c_oil->oif_flags[oif_vif_index]
                                    & PIM_OIF_FLAG_PROTO_IGMP) {
-                                       strcpy(proto, "IGMP");
+                                       strlcpy(proto, "IGMP", sizeof(proto));
                                }
 
                                if (c_oil->oif_flags[oif_vif_index]
                                    & PIM_OIF_FLAG_PROTO_VXLAN) {
-                                       strcpy(proto, "VxLAN");
-                               }
-
-                               if (c_oil->oif_flags[oif_vif_index]
-                                   & PIM_OIF_FLAG_PROTO_SOURCE) {
-                                       strcpy(proto, "SRC");
+                                       strlcpy(proto, "VxLAN", sizeof(proto));
                                }
 
                                if (c_oil->oif_flags[oif_vif_index]
                                    & PIM_OIF_FLAG_PROTO_STAR) {
-                                       strcpy(proto, "STAR");
+                                       strlcpy(proto, "STAR", sizeof(proto));
                                }
 
                                vty_out(vty,
@@ -4785,9 +5408,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
                found_oif = 0;
 
                if (ifp_in)
-                       strcpy(in_ifname, ifp_in->name);
+                       strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
                else
-                       strcpy(in_ifname, "<iif?>");
+                       strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
 
                if (uj) {
 
@@ -4814,7 +5437,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
                        json_object_string_add(json_source, "iif", in_ifname);
                        json_oil = NULL;
                } else {
-                       strcpy(proto, "STATIC");
+                       strlcpy(proto, "STATIC", sizeof(proto));
                }
 
                for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
@@ -4836,9 +5459,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
                        found_oif = 1;
 
                        if (ifp_out)
-                               strcpy(out_ifname, ifp_out->name);
+                               strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
                        else
-                               strcpy(out_ifname, "<oif?>");
+                               strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
 
                        if (uj) {
                                json_ifp_out = json_object_new_object();
@@ -4959,21 +5582,64 @@ DEFUN (show_ip_mroute_vrf_all,
        if (argv_find(argv, argc, "fill", &idx))
                fill = true;
 
-       if (uj)
-               vty_out(vty, "{ ");
-       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
-               if (uj) {
-                       if (!first)
-                               vty_out(vty, ", ");
-                       vty_out(vty, " \"%s\": ", vrf->name);
-                       first = false;
-               } else
-                       vty_out(vty, "VRF: %s\n", vrf->name);
-               show_mroute(vrf->info, vty, &sg, fill, uj);
+       if (uj)
+               vty_out(vty, "{ ");
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               if (uj) {
+                       if (!first)
+                               vty_out(vty, ", ");
+                       vty_out(vty, " \"%s\": ", vrf->name);
+                       first = false;
+               } else
+                       vty_out(vty, "VRF: %s\n", vrf->name);
+               show_mroute(vrf->info, vty, &sg, fill, uj);
+       }
+       if (uj)
+               vty_out(vty, "}\n");
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (clear_ip_mroute_count,
+       clear_ip_mroute_count_cmd,
+       "clear ip mroute [vrf NAME] count",
+       CLEAR_STR
+       IP_STR
+       MROUTE_STR
+       VRF_CMD_HELP_STR
+       "Route and packet count data\n")
+{
+       int idx = 2;
+       struct listnode *node;
+       struct channel_oil *c_oil;
+       struct static_route *sr;
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct pim_instance *pim;
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       pim = vrf->info;
+       for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
+               if (!c_oil->installed)
+                       continue;
+
+               pim_mroute_update_counters(c_oil);
+               c_oil->cc.origpktcnt = c_oil->cc.pktcnt;
+               c_oil->cc.origbytecnt = c_oil->cc.bytecnt;
+               c_oil->cc.origwrong_if = c_oil->cc.wrong_if;
        }
-       if (uj)
-               vty_out(vty, "}\n");
 
+       for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
+               if (!sr->c_oil.installed)
+                       continue;
+
+               pim_mroute_update_counters(&sr->c_oil);
+
+               sr->c_oil.cc.origpktcnt = sr->c_oil.cc.pktcnt;
+               sr->c_oil.cc.origbytecnt = sr->c_oil.cc.bytecnt;
+               sr->c_oil.cc.origwrong_if = sr->c_oil.cc.wrong_if;
+       }
        return CMD_SUCCESS;
 }
 
@@ -4981,7 +5647,7 @@ static void show_mroute_count(struct pim_instance *pim, struct vty *vty)
 {
        struct listnode *node;
        struct channel_oil *c_oil;
-       struct static_route *s_route;
+       struct static_route *sr;
 
        vty_out(vty, "\n");
 
@@ -5005,28 +5671,30 @@ static void show_mroute_count(struct pim_instance *pim, struct vty *vty)
 
                vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n",
                        source_str, group_str, c_oil->cc.lastused / 100,
-                       c_oil->cc.pktcnt, c_oil->cc.bytecnt,
-                       c_oil->cc.wrong_if);
+                       c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
+                       c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
+                       c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
        }
 
-       for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
+       for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
                char group_str[INET_ADDRSTRLEN];
                char source_str[INET_ADDRSTRLEN];
 
-               if (!s_route->c_oil.installed)
+               if (!sr->c_oil.installed)
                        continue;
 
-               pim_mroute_update_counters(&s_route->c_oil);
+               pim_mroute_update_counters(&sr->c_oil);
 
-               pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp,
+               pim_inet4_dump("<group?>", sr->c_oil.oil.mfcc_mcastgrp,
                               group_str, sizeof(group_str));
-               pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin,
+               pim_inet4_dump("<source?>", sr->c_oil.oil.mfcc_origin,
                               source_str, sizeof(source_str));
 
                vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n",
-                       source_str, group_str, s_route->c_oil.cc.lastused,
-                       s_route->c_oil.cc.pktcnt, s_route->c_oil.cc.bytecnt,
-                       s_route->c_oil.cc.wrong_if);
+                       source_str, group_str, sr->c_oil.cc.lastused,
+                       sr->c_oil.cc.pktcnt - sr->c_oil.cc.origpktcnt,
+                       sr->c_oil.cc.bytecnt - sr->c_oil.cc.origbytecnt,
+                       sr->c_oil.cc.wrong_if - sr->c_oil.cc.origwrong_if);
        }
 }
 
@@ -5080,6 +5748,97 @@ DEFUN (show_ip_mroute_count_vrf_all,
        return CMD_SUCCESS;
 }
 
+static void show_mroute_summary(struct pim_instance *pim, struct vty *vty)
+{
+       struct listnode *node;
+       struct channel_oil *c_oil;
+       struct static_route *s_route;
+       uint32_t starg_sw_mroute_cnt = 0;
+       uint32_t sg_sw_mroute_cnt = 0;
+       uint32_t starg_hw_mroute_cnt = 0;
+       uint32_t sg_hw_mroute_cnt = 0;
+
+       vty_out(vty, "Mroute Type    Installed/Total\n");
+
+       for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
+               if (!c_oil->installed) {
+                       if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
+                               starg_sw_mroute_cnt++;
+                       else
+                               sg_sw_mroute_cnt++;
+               } else {
+                       if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
+                               starg_hw_mroute_cnt++;
+                       else
+                               sg_hw_mroute_cnt++;
+               }
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
+               if (!s_route->c_oil.installed) {
+                       if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
+                               starg_sw_mroute_cnt++;
+                       else
+                               sg_sw_mroute_cnt++;
+               } else {
+                       if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
+                               starg_hw_mroute_cnt++;
+                       else
+                               sg_hw_mroute_cnt++;
+               }
+       }
+
+       vty_out(vty, "%-20s %d/%d\n", "(*, G)", starg_hw_mroute_cnt,
+               starg_sw_mroute_cnt + starg_hw_mroute_cnt);
+       vty_out(vty, "%-20s %d/%d\n", "(S, G)", sg_hw_mroute_cnt,
+               sg_sw_mroute_cnt + sg_hw_mroute_cnt);
+       vty_out(vty, "------\n");
+       vty_out(vty, "%-20s %d/%d\n", "Total",
+               (starg_hw_mroute_cnt + sg_hw_mroute_cnt),
+               (starg_sw_mroute_cnt +
+                starg_hw_mroute_cnt +
+                sg_sw_mroute_cnt +
+                sg_hw_mroute_cnt));
+}
+
+DEFUN (show_ip_mroute_summary,
+       show_ip_mroute_summary_cmd,
+       "show ip mroute [vrf NAME] summary",
+       SHOW_STR
+       IP_STR
+       MROUTE_STR
+       VRF_CMD_HELP_STR
+       "Summary of all mroutes\n")
+{
+       int idx = 2;
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       show_mroute_summary(vrf->info, vty);
+       return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_mroute_summary_vrf_all,
+       show_ip_mroute_summary_vrf_all_cmd,
+       "show ip mroute vrf all summary",
+       SHOW_STR
+       IP_STR
+       MROUTE_STR
+       VRF_CMD_HELP_STR
+       "Summary of all mroutes\n")
+{
+       struct vrf *vrf;
+
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               vty_out(vty, "VRF: %s\n", vrf->name);
+               show_mroute_summary(vrf->info, vty);
+       }
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (show_ip_rib,
        show_ip_rib_cmd,
        "show ip rib [vrf NAME] A.B.C.D",
@@ -5196,7 +5955,13 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
 {
        int result;
 
-       result = pim_rp_new(pim, rp, group, plist);
+       result = pim_rp_new_config(pim, rp, group, plist);
+
+       if (result == PIM_GROUP_BAD_ADDR_MASK_COMBO) {
+               vty_out(vty, "%% Inconsistent address and mask: %s\n",
+                       group);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
        if (result == PIM_GROUP_BAD_ADDRESS) {
                vty_out(vty, "%% Bad group address specified: %s\n", group);
@@ -5522,7 +6287,7 @@ static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
                                const char *rp, const char *group,
                                const char *plist)
 {
-       int result = pim_rp_del(pim, rp, group, plist);
+       int result = pim_rp_del_config(pim, rp, group, plist);
 
        if (result == PIM_GROUP_BAD_ADDRESS) {
                vty_out(vty, "%% Bad group address specified: %s\n", group);
@@ -5741,6 +6506,27 @@ DEFUN (show_ip_pim_group_type,
        return CMD_SUCCESS;
 }
 
+DEFUN (show_ip_pim_bsr,
+       show_ip_pim_bsr_cmd,
+       "show ip pim bsr [json]",
+       SHOW_STR
+       IP_STR
+       PIM_STR
+       "boot-strap router information\n"
+       JSON_STR)
+{
+       int idx = 2;
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       bool uj = use_json(argc, argv);
+
+       if (!vrf)
+               return CMD_WARNING;
+
+       pim_show_bsr(vrf->info, vty, uj);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (ip_ssmpingd,
        ip_ssmpingd_cmd,
        "ip ssmpingd [A.B.C.D]",
@@ -6418,6 +7204,106 @@ DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,
        return CMD_SUCCESS;
 }
 
+#define IGMP_LAST_MEMBER_QUERY_COUNT_MIN (1)
+#define IGMP_LAST_MEMBER_QUERY_COUNT_MAX (7)
+
+DEFUN (interface_ip_igmp_last_member_query_count,
+       interface_ip_igmp_last_member_query_count_cmd,
+       "ip igmp last-member-query-count (1-7)",
+       IP_STR
+       IFACE_IGMP_STR
+       IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR
+       "Last member query count\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp = ifp->info;
+       int last_member_query_count;
+       int ret;
+
+       if (!pim_ifp) {
+               ret = pim_cmd_igmp_start(vty, ifp);
+               if (ret != CMD_SUCCESS)
+                       return ret;
+               pim_ifp = ifp->info;
+       }
+
+       last_member_query_count = atoi(argv[3]->arg);
+
+       pim_ifp->igmp_last_member_query_count = last_member_query_count;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (interface_no_ip_igmp_last_member_query_count,
+       interface_no_ip_igmp_last_member_query_count_cmd,
+       "no ip igmp last-member-query-count",
+       NO_STR
+       IP_STR
+       IFACE_IGMP_STR
+       IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR)
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp = ifp->info;
+
+       if (!pim_ifp)
+               return CMD_SUCCESS;
+
+       pim_ifp->igmp_last_member_query_count =
+               IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
+
+       return CMD_SUCCESS;
+}
+
+#define IGMP_LAST_MEMBER_QUERY_INTERVAL_MIN (1)
+#define IGMP_LAST_MEMBER_QUERY_INTERVAL_MAX (255)
+
+DEFUN (interface_ip_igmp_last_member_query_interval,
+       interface_ip_igmp_last_member_query_interval_cmd,
+       "ip igmp last-member-query-interval (1-255)",
+       IP_STR
+       IFACE_IGMP_STR
+       IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR
+       "Last member query interval in deciseconds\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp = ifp->info;
+       int last_member_query_interval;
+       int ret;
+
+       if (!pim_ifp) {
+               ret = pim_cmd_igmp_start(vty, ifp);
+               if (ret != CMD_SUCCESS)
+                       return ret;
+               pim_ifp = ifp->info;
+       }
+
+       last_member_query_interval = atoi(argv[3]->arg);
+       pim_ifp->igmp_specific_query_max_response_time_dsec
+               = last_member_query_interval;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (interface_no_ip_igmp_last_member_query_interval,
+       interface_no_ip_igmp_last_member_query_interval_cmd,
+       "no ip igmp last-member-query-interval",
+       NO_STR
+       IP_STR
+       IFACE_IGMP_STR
+       IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR)
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp = ifp->info;
+
+       if (!pim_ifp)
+               return CMD_SUCCESS;
+
+       pim_ifp->igmp_specific_query_max_response_time_dsec =
+               IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (interface_ip_pim_drprio,
        interface_ip_pim_drprio_cmd,
        "ip pim drpriority (1-4294967295)",
@@ -6769,7 +7655,7 @@ DEFUN (interface_ip_mroute,
        pim = pim_ifp->pim;
 
        oifname = argv[idx_interface]->arg;
-       oif = if_lookup_by_name(oifname, pim->vrf_id);
+       oif = if_lookup_by_name(oifname, pim->vrf);
        if (!oif) {
                vty_out(vty, "No such interface name %s\n", oifname);
                return CMD_WARNING;
@@ -6820,7 +7706,7 @@ DEFUN (interface_ip_mroute_source,
        pim = pim_ifp->pim;
 
        oifname = argv[idx_interface]->arg;
-       oif = if_lookup_by_name(oifname, pim->vrf_id);
+       oif = if_lookup_by_name(oifname, pim->vrf);
        if (!oif) {
                vty_out(vty, "No such interface name %s\n", oifname);
                return CMD_WARNING;
@@ -6875,7 +7761,7 @@ DEFUN (interface_no_ip_mroute,
        pim = pim_ifp->pim;
 
        oifname = argv[idx_interface]->arg;
-       oif = if_lookup_by_name(oifname, pim->vrf_id);
+       oif = if_lookup_by_name(oifname, pim->vrf);
        if (!oif) {
                vty_out(vty, "No such interface name %s\n", oifname);
                return CMD_WARNING;
@@ -6927,7 +7813,7 @@ DEFUN (interface_no_ip_mroute_source,
        pim = pim_ifp->pim;
 
        oifname = argv[idx_interface]->arg;
-       oif = if_lookup_by_name(oifname, pim->vrf_id);
+       oif = if_lookup_by_name(oifname, pim->vrf);
        if (!oif) {
                vty_out(vty, "No such interface name %s\n", oifname);
                return CMD_WARNING;
@@ -7189,6 +8075,7 @@ DEFUN (debug_pim,
        PIM_DO_DEBUG_PIM_TRACE;
        PIM_DO_DEBUG_MSDP_EVENTS;
        PIM_DO_DEBUG_MSDP_PACKETS;
+       PIM_DO_DEBUG_BSM;
        return CMD_SUCCESS;
 }
 
@@ -7207,6 +8094,7 @@ DEFUN (no_debug_pim,
 
        PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
        PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
+       PIM_DONT_DEBUG_BSM;
 
        return CMD_SUCCESS;
 }
@@ -7592,6 +8480,30 @@ DEFUN (no_debug_mtrace,
        return CMD_SUCCESS;
 }
 
+DEFUN (debug_bsm,
+       debug_bsm_cmd,
+       "debug pim bsm",
+       DEBUG_STR
+       DEBUG_PIM_STR
+       DEBUG_PIM_BSM_STR)
+{
+       PIM_DO_DEBUG_BSM;
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bsm,
+       no_debug_bsm_cmd,
+       "no debug pim bsm",
+       NO_STR
+       DEBUG_STR
+       DEBUG_PIM_STR
+       DEBUG_PIM_BSM_STR)
+{
+       PIM_DONT_DEBUG_BSM;
+       return CMD_SUCCESS;
+}
+
+
 DEFUN_NOSH (show_debugging_pim,
            show_debugging_pim_cmd,
            "show debugging [pim]",
@@ -7715,11 +8627,107 @@ DEFUN (no_ip_pim_bfd,
        return CMD_SUCCESS;
 }
 
+DEFUN (ip_pim_bsm,
+       ip_pim_bsm_cmd,
+       "ip pim bsm",
+       IP_STR
+       PIM_STR
+       "Enables BSM support on the interface\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp = ifp->info;
+
+       if (!pim_ifp) {
+               if (!pim_cmd_interface_add(ifp)) {
+                       vty_out(vty, "Could not enable PIM SM on interface\n");
+                       return CMD_WARNING;
+               }
+       }
+
+       pim_ifp = ifp->info;
+       pim_ifp->bsm_enable = true;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_bsm,
+       no_ip_pim_bsm_cmd,
+       "no ip pim bsm",
+       NO_STR
+       IP_STR
+       PIM_STR
+       "Disables BSM support\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp = ifp->info;
+
+       if (!pim_ifp) {
+               vty_out(vty, "Pim not enabled on this interface\n");
+               return CMD_WARNING;
+       }
+
+       pim_ifp->bsm_enable = false;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (ip_pim_ucast_bsm,
+       ip_pim_ucast_bsm_cmd,
+       "ip pim unicast-bsm",
+       IP_STR
+       PIM_STR
+       "Accept/Send unicast BSM on the interface\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp = ifp->info;
+
+       if (!pim_ifp) {
+               if (!pim_cmd_interface_add(ifp)) {
+                       vty_out(vty, "Could not enable PIM SM on interface\n");
+                       return CMD_WARNING;
+               }
+       }
+
+       pim_ifp = ifp->info;
+       pim_ifp->ucast_bsm_accept = true;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_pim_ucast_bsm,
+       no_ip_pim_ucast_bsm_cmd,
+       "no ip pim unicast-bsm",
+       NO_STR
+       IP_STR
+       PIM_STR
+       "Block send/receive unicast BSM on this interface\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp = ifp->info;
+
+       if (!pim_ifp) {
+               vty_out(vty, "Pim not enabled on this interface\n");
+               return CMD_WARNING;
+       }
+
+       pim_ifp->ucast_bsm_accept = false;
+
+       return CMD_SUCCESS;
+}
+
 #if HAVE_BFDD > 0
 DEFUN_HIDDEN(
+       ip_pim_bfd_param,
+       ip_pim_bfd_param_cmd,
+       "ip pim bfd (2-255) (50-60000) (50-60000)",
+       IP_STR
+       PIM_STR
+       "Enables BFD support\n"
+       "Detect Multiplier\n"
+       "Required min receive interval\n"
+       "Desired min transmit interval\n")
 #else
 DEFUN(
-#endif /* HAVE_BFDD */
        ip_pim_bfd_param,
        ip_pim_bfd_param_cmd,
        "ip pim bfd (2-255) (50-60000) (50-60000)",
@@ -7729,6 +8737,7 @@ DEFUN(
        "Detect Multiplier\n"
        "Required min receive interval\n"
        "Desired min transmit interval\n")
+#endif /* HAVE_BFDD */
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx_number = 3;
@@ -8232,7 +9241,7 @@ static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty,
                        pim_time_uptime(timebuf, sizeof(timebuf),
                                        now - mp->uptime);
                } else {
-                       strcpy(timebuf, "-");
+                       strlcpy(timebuf, "-", sizeof(timebuf));
                }
                pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
                pim_inet4_dump("<local?>", mp->local, local_str,
@@ -8289,7 +9298,7 @@ static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty,
                        pim_time_uptime(timebuf, sizeof(timebuf),
                                        now - mp->uptime);
                } else {
-                       strcpy(timebuf, "-");
+                       strlcpy(timebuf, "-", sizeof(timebuf));
                }
                pim_inet4_dump("<local?>", mp->local, local_str,
                               sizeof(local_str));
@@ -8468,18 +9477,18 @@ static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj)
                if (sa->flags & PIM_MSDP_SAF_PEER) {
                        pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
                        if (sa->up) {
-                               strcpy(spt_str, "yes");
+                               strlcpy(spt_str, "yes", sizeof(spt_str));
                        } else {
-                               strcpy(spt_str, "no");
+                               strlcpy(spt_str, "no", sizeof(spt_str));
                        }
                } else {
-                       strcpy(rp_str, "-");
-                       strcpy(spt_str, "-");
+                       strlcpy(rp_str, "-", sizeof(rp_str));
+                       strlcpy(spt_str, "-", sizeof(spt_str));
                }
                if (sa->flags & PIM_MSDP_SAF_LOCAL) {
-                       strcpy(local_str, "yes");
+                       strlcpy(local_str, "yes", sizeof(local_str));
                } else {
-                       strcpy(local_str, "no");
+                       strlcpy(local_str, "no", sizeof(local_str));
                }
                if (uj) {
                        json_object_object_get_ex(json, grp_str, &json_group);
@@ -8533,19 +9542,19 @@ static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa,
                pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
                pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str));
                if (sa->up) {
-                       strcpy(spt_str, "yes");
+                       strlcpy(spt_str, "yes", sizeof(spt_str));
                } else {
-                       strcpy(spt_str, "no");
+                       strlcpy(spt_str, "no", sizeof(spt_str));
                }
        } else {
-               strcpy(rp_str, "-");
-               strcpy(peer_str, "-");
-               strcpy(spt_str, "-");
+               strlcpy(rp_str, "-", sizeof(rp_str));
+               strlcpy(peer_str, "-", sizeof(peer_str));
+               strlcpy(spt_str, "-", sizeof(spt_str));
        }
        if (sa->flags & PIM_MSDP_SAF_LOCAL) {
-               strcpy(local_str, "yes");
+               strlcpy(local_str, "yes", sizeof(local_str));
        } else {
-               strcpy(local_str, "no");
+               strlcpy(local_str, "no", sizeof(local_str));
        }
        pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer),
                                 sa->sa_state_timer);
@@ -9127,7 +10136,7 @@ DEFUN_HIDDEN (ip_pim_mlag,
 
        idx = 3;
        peerlink = argv[idx]->arg;
-       ifp = if_lookup_by_name(peerlink, VRF_DEFAULT);
+       ifp = if_lookup_by_name(peerlink, vrf_lookup_by_id(VRF_DEFAULT));
        if (!ifp) {
                vty_out(vty, "No such interface name %s\n", peerlink);
                return CMD_WARNING;
@@ -9259,6 +10268,14 @@ void pim_cmd_init(void)
                        &interface_ip_igmp_query_max_response_time_dsec_cmd);
        install_element(INTERFACE_NODE,
                        &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
+       install_element(INTERFACE_NODE,
+                       &interface_ip_igmp_last_member_query_count_cmd);
+       install_element(INTERFACE_NODE,
+                       &interface_no_ip_igmp_last_member_query_count_cmd);
+       install_element(INTERFACE_NODE,
+                       &interface_ip_igmp_last_member_query_interval_cmd);
+       install_element(INTERFACE_NODE,
+                       &interface_no_ip_igmp_last_member_query_interval_cmd);
        install_element(INTERFACE_NODE, &interface_ip_pim_activeactive_cmd);
        install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
        install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
@@ -9312,24 +10329,32 @@ void pim_cmd_init(void)
        install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
        install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
        install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
+       install_element(VIEW_NODE, &show_ip_pim_bsr_cmd);
        install_element(VIEW_NODE, &show_ip_multicast_cmd);
        install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
        install_element(VIEW_NODE, &show_ip_mroute_cmd);
        install_element(VIEW_NODE, &show_ip_mroute_vrf_all_cmd);
        install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
        install_element(VIEW_NODE, &show_ip_mroute_count_vrf_all_cmd);
+       install_element(VIEW_NODE, &show_ip_mroute_summary_cmd);
+       install_element(VIEW_NODE, &show_ip_mroute_summary_vrf_all_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(VIEW_NODE, &show_ip_pim_bsrp_cmd);
+       install_element(VIEW_NODE, &show_ip_pim_bsm_db_cmd);
+       install_element(VIEW_NODE, &show_ip_pim_statistics_cmd);
 
+       install_element(ENABLE_NODE, &clear_ip_mroute_count_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, &clear_ip_pim_statistics_cmd);
 
        install_element(ENABLE_NODE, &debug_igmp_cmd);
        install_element(ENABLE_NODE, &no_debug_igmp_cmd);
@@ -9377,6 +10402,8 @@ void pim_cmd_init(void)
        install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
        install_element(ENABLE_NODE, &debug_mtrace_cmd);
        install_element(ENABLE_NODE, &no_debug_mtrace_cmd);
+       install_element(ENABLE_NODE, &debug_bsm_cmd);
+       install_element(ENABLE_NODE, &no_debug_bsm_cmd);
 
        install_element(CONFIG_NODE, &debug_igmp_cmd);
        install_element(CONFIG_NODE, &no_debug_igmp_cmd);
@@ -9420,6 +10447,8 @@ void pim_cmd_init(void)
        install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
        install_element(CONFIG_NODE, &debug_mtrace_cmd);
        install_element(CONFIG_NODE, &no_debug_mtrace_cmd);
+       install_element(CONFIG_NODE, &debug_bsm_cmd);
+       install_element(CONFIG_NODE, &no_debug_bsm_cmd);
 
        install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd);
        install_element(VRF_NODE, &ip_msdp_mesh_group_member_cmd);
@@ -9443,6 +10472,11 @@ void pim_cmd_init(void)
        install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_work_cmd);
        install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
        install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd);
+       /* Install BSM command */
+       install_element(INTERFACE_NODE, &ip_pim_bsm_cmd);
+       install_element(INTERFACE_NODE, &no_ip_pim_bsm_cmd);
+       install_element(INTERFACE_NODE, &ip_pim_ucast_bsm_cmd);
+       install_element(INTERFACE_NODE, &no_ip_pim_ucast_bsm_cmd);
        /* Install BFD command */
        install_element(INTERFACE_NODE, &ip_pim_bfd_cmd);
        install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd);