back to topotato report
topotato coverage report
Current view: top level - pimd - pim_cmd_common.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 533 3115 17.1 %
Date: 2023-02-24 14:41:08 Functions: 23 131 17.6 %

          Line data    Source code
       1             : /*
       2             :  * PIM for IPv6 FRR
       3             :  * Copyright (C) 2022  Vmware, Inc.
       4             :  *                     Mobashshera Rasool <mrasool@vmware.com>
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 2 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "lib/json.h"
      24             : #include "command.h"
      25             : #include "if.h"
      26             : #include "prefix.h"
      27             : #include "zclient.h"
      28             : #include "plist.h"
      29             : #include "hash.h"
      30             : #include "nexthop.h"
      31             : #include "vrf.h"
      32             : #include "ferr.h"
      33             : #include "lib/srcdest_table.h"
      34             : #include "lib/linklist.h"
      35             : #include "termtable.h"
      36             : 
      37             : #include "pimd.h"
      38             : #include "pim_instance.h"
      39             : #include "pim_vty.h"
      40             : #include "lib/northbound_cli.h"
      41             : #include "pim_errors.h"
      42             : #include "pim_nb.h"
      43             : #include "pim_mroute.h"
      44             : #include "pim_cmd.h"
      45             : #include "pim6_cmd.h"
      46             : #include "pim_cmd_common.h"
      47             : #include "pim_time.h"
      48             : #include "pim_zebra.h"
      49             : #include "pim_zlookup.h"
      50             : #include "pim_iface.h"
      51             : #include "pim_macro.h"
      52             : #include "pim_neighbor.h"
      53             : #include "pim_nht.h"
      54             : #include "pim_sock.h"
      55             : #include "pim_ssm.h"
      56             : #include "pim_static.h"
      57             : #include "pim_addr.h"
      58             : #include "pim_static.h"
      59             : #include "pim_util.h"
      60             : #include "pim6_mld.h"
      61             : 
      62             : /**
      63             :  * Get current node VRF name.
      64             :  *
      65             :  * NOTE:
      66             :  * In case of failure it will print error message to user.
      67             :  *
      68             :  * \returns name or NULL if failed to get VRF.
      69             :  */
      70           5 : const char *pim_cli_get_vrf_name(struct vty *vty)
      71             : {
      72           5 :         const struct lyd_node *vrf_node;
      73             : 
      74             :         /* Not inside any VRF context. */
      75           5 :         if (vty->xpath_index == 0)
      76           5 :                 return VRF_DEFAULT_NAME;
      77             : 
      78           0 :         vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
      79           0 :         if (vrf_node == NULL) {
      80           0 :                 vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
      81           0 :                 return NULL;
      82             :         }
      83             : 
      84           0 :         return yang_dnode_get_string(vrf_node, "./name");
      85             : }
      86             : 
      87           1 : int pim_process_join_prune_cmd(struct vty *vty, const char *jpi_str)
      88             : {
      89           1 :         char xpath[XPATH_MAXLEN];
      90             : 
      91           1 :         snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
      92             :                  FRR_PIM_AF_XPATH_VAL);
      93           1 :         strlcat(xpath, "/join-prune-interval", sizeof(xpath));
      94             : 
      95           1 :         nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, jpi_str);
      96             : 
      97           1 :         return nb_cli_apply_changes(vty, NULL);
      98             : }
      99             : 
     100           0 : int pim_process_no_join_prune_cmd(struct vty *vty)
     101             : {
     102           0 :         char xpath[XPATH_MAXLEN];
     103             : 
     104           0 :         snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
     105             :                  FRR_PIM_AF_XPATH_VAL);
     106           0 :         strlcat(xpath, "/join-prune-interval", sizeof(xpath));
     107             : 
     108           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     109             : 
     110           0 :         return nb_cli_apply_changes(vty, NULL);
     111             : }
     112             : 
     113           0 : int pim_process_spt_switchover_infinity_cmd(struct vty *vty)
     114             : {
     115           0 :         const char *vrfname;
     116           0 :         char spt_plist_xpath[XPATH_MAXLEN];
     117           0 :         char spt_action_xpath[XPATH_MAXLEN];
     118             : 
     119           0 :         vrfname = pim_cli_get_vrf_name(vty);
     120           0 :         if (vrfname == NULL)
     121             :                 return CMD_WARNING_CONFIG_FAILED;
     122             : 
     123           0 :         snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
     124             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
     125             :                  FRR_PIM_AF_XPATH_VAL);
     126           0 :         strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
     127             :                 sizeof(spt_plist_xpath));
     128             : 
     129           0 :         snprintf(spt_action_xpath, sizeof(spt_action_xpath),
     130             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
     131             :                  FRR_PIM_AF_XPATH_VAL);
     132           0 :         strlcat(spt_action_xpath, "/spt-switchover/spt-action",
     133             :                 sizeof(spt_action_xpath));
     134             : 
     135           0 :         if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
     136           0 :                 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
     137             :                                       NULL);
     138           0 :         nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
     139             :                               "PIM_SPT_INFINITY");
     140             : 
     141           0 :         return nb_cli_apply_changes(vty, NULL);
     142             : }
     143             : 
     144           0 : int pim_process_spt_switchover_prefixlist_cmd(struct vty *vty,
     145             :                                               const char *plist)
     146             : {
     147           0 :         const char *vrfname;
     148           0 :         char spt_plist_xpath[XPATH_MAXLEN];
     149           0 :         char spt_action_xpath[XPATH_MAXLEN];
     150             : 
     151           0 :         vrfname = pim_cli_get_vrf_name(vty);
     152           0 :         if (vrfname == NULL)
     153             :                 return CMD_WARNING_CONFIG_FAILED;
     154             : 
     155           0 :         snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
     156             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
     157             :                  FRR_PIM_AF_XPATH_VAL);
     158           0 :         strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
     159             :                 sizeof(spt_plist_xpath));
     160             : 
     161           0 :         snprintf(spt_action_xpath, sizeof(spt_action_xpath),
     162             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
     163             :                  FRR_PIM_AF_XPATH_VAL);
     164           0 :         strlcat(spt_action_xpath, "/spt-switchover/spt-action",
     165             :                 sizeof(spt_action_xpath));
     166             : 
     167           0 :         nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
     168             :                               "PIM_SPT_INFINITY");
     169           0 :         nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
     170             :                               plist);
     171             : 
     172           0 :         return nb_cli_apply_changes(vty, NULL);
     173             : }
     174             : 
     175           0 : int pim_process_no_spt_switchover_cmd(struct vty *vty)
     176             : {
     177           0 :         const char *vrfname;
     178           0 :         char spt_plist_xpath[XPATH_MAXLEN];
     179           0 :         char spt_action_xpath[XPATH_MAXLEN];
     180             : 
     181           0 :         vrfname = pim_cli_get_vrf_name(vty);
     182           0 :         if (vrfname == NULL)
     183             :                 return CMD_WARNING_CONFIG_FAILED;
     184             : 
     185           0 :         snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
     186             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
     187             :                  FRR_PIM_AF_XPATH_VAL);
     188           0 :         strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
     189             :                 sizeof(spt_plist_xpath));
     190             : 
     191           0 :         snprintf(spt_action_xpath, sizeof(spt_action_xpath),
     192             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
     193             :                  FRR_PIM_AF_XPATH_VAL);
     194           0 :         strlcat(spt_action_xpath, "/spt-switchover/spt-action",
     195             :                 sizeof(spt_action_xpath));
     196             : 
     197           0 :         nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
     198           0 :         nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
     199             :                               "PIM_SPT_IMMEDIATE");
     200             : 
     201           0 :         return nb_cli_apply_changes(vty, NULL);
     202             : }
     203             : 
     204           0 : int pim_process_pim_packet_cmd(struct vty *vty, const char *packet)
     205             : {
     206           0 :         char xpath[XPATH_MAXLEN];
     207             : 
     208           0 :         snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
     209             :                  FRR_PIM_AF_XPATH_VAL);
     210           0 :         strlcat(xpath, "/packets", sizeof(xpath));
     211             : 
     212           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, packet);
     213             : 
     214           0 :         return nb_cli_apply_changes(vty, NULL);
     215             : }
     216             : 
     217           0 : int pim_process_no_pim_packet_cmd(struct vty *vty)
     218             : {
     219           0 :         char xpath[XPATH_MAXLEN];
     220             : 
     221           0 :         snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
     222             :                  FRR_PIM_AF_XPATH_VAL);
     223           0 :         strlcat(xpath, "/packets", sizeof(xpath));
     224             : 
     225           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     226             : 
     227           0 :         return nb_cli_apply_changes(vty, NULL);
     228             : }
     229             : 
     230           0 : int pim_process_keepalivetimer_cmd(struct vty *vty, const char *kat)
     231             : {
     232           0 :         const char *vrfname;
     233           0 :         char ka_timer_xpath[XPATH_MAXLEN];
     234             : 
     235           0 :         vrfname = pim_cli_get_vrf_name(vty);
     236           0 :         if (vrfname == NULL)
     237             :                 return CMD_WARNING_CONFIG_FAILED;
     238             : 
     239           0 :         snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
     240             :                  "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
     241           0 :         strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
     242             : 
     243           0 :         nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
     244             :                               kat);
     245             : 
     246           0 :         return nb_cli_apply_changes(vty, NULL);
     247             : }
     248             : 
     249           0 : int pim_process_no_keepalivetimer_cmd(struct vty *vty)
     250             : {
     251           0 :         const char *vrfname;
     252           0 :         char ka_timer_xpath[XPATH_MAXLEN];
     253             : 
     254           0 :         vrfname = pim_cli_get_vrf_name(vty);
     255           0 :         if (vrfname == NULL)
     256             :                 return CMD_WARNING_CONFIG_FAILED;
     257             : 
     258           0 :         snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
     259             :                  "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
     260           0 :         strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
     261             : 
     262           0 :         nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_DESTROY, NULL);
     263             : 
     264           0 :         return nb_cli_apply_changes(vty, NULL);
     265             : }
     266             : 
     267           0 : int pim_process_rp_kat_cmd(struct vty *vty, const char *rpkat)
     268             : {
     269           0 :         const char *vrfname;
     270           0 :         char rp_ka_timer_xpath[XPATH_MAXLEN];
     271             : 
     272           0 :         vrfname = pim_cli_get_vrf_name(vty);
     273           0 :         if (vrfname == NULL)
     274             :                 return CMD_WARNING_CONFIG_FAILED;
     275             : 
     276           0 :         snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
     277             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
     278             :                  FRR_PIM_AF_XPATH_VAL);
     279           0 :         strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
     280             :                 sizeof(rp_ka_timer_xpath));
     281             : 
     282           0 :         nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
     283             :                               rpkat);
     284             : 
     285           0 :         return nb_cli_apply_changes(vty, NULL);
     286             : }
     287             : 
     288           0 : int pim_process_no_rp_kat_cmd(struct vty *vty)
     289             : {
     290           0 :         const char *vrfname;
     291           0 :         char rp_ka_timer[6];
     292           0 :         char rp_ka_timer_xpath[XPATH_MAXLEN];
     293           0 :         uint v;
     294           0 :         char rs_timer_xpath[XPATH_MAXLEN];
     295             : 
     296           0 :         snprintf(rs_timer_xpath, sizeof(rs_timer_xpath),
     297             :                  FRR_PIM_ROUTER_XPATH, FRR_PIM_AF_XPATH_VAL);
     298           0 :         strlcat(rs_timer_xpath, "/register-suppress-time",
     299             :                 sizeof(rs_timer_xpath));
     300             : 
     301             :         /* RFC4601 */
     302           0 :         v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s",
     303             :                                   rs_timer_xpath);
     304           0 :         v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
     305           0 :         if (v > UINT16_MAX)
     306             :                 v = UINT16_MAX;
     307           0 :         snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%u", v);
     308             : 
     309           0 :         vrfname = pim_cli_get_vrf_name(vty);
     310           0 :         if (vrfname == NULL)
     311             :                 return CMD_WARNING_CONFIG_FAILED;
     312             : 
     313           0 :         snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
     314             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
     315             :                  FRR_PIM_AF_XPATH_VAL);
     316           0 :         strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
     317             :                 sizeof(rp_ka_timer_xpath));
     318             : 
     319           0 :         nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
     320             :                               rp_ka_timer);
     321             : 
     322           0 :         return nb_cli_apply_changes(vty, NULL);
     323             : }
     324             : 
     325           0 : int pim_process_register_suppress_cmd(struct vty *vty, const char *rst)
     326             : {
     327           0 :         char xpath[XPATH_MAXLEN];
     328             : 
     329           0 :         snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
     330             :                  FRR_PIM_AF_XPATH_VAL);
     331           0 :         strlcat(xpath, "/register-suppress-time", sizeof(xpath));
     332             : 
     333           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rst);
     334             : 
     335           0 :         return nb_cli_apply_changes(vty, NULL);
     336             : }
     337             : 
     338           0 : int pim_process_no_register_suppress_cmd(struct vty *vty)
     339             : {
     340           0 :         char xpath[XPATH_MAXLEN];
     341             : 
     342           0 :         snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
     343             :                  FRR_PIM_AF_XPATH_VAL);
     344           0 :         strlcat(xpath, "/register-suppress-time", sizeof(xpath));
     345             : 
     346           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     347             : 
     348           0 :         return nb_cli_apply_changes(vty, NULL);
     349             : }
     350             : 
     351          50 : int pim_process_ip_pim_cmd(struct vty *vty)
     352             : {
     353          50 :         nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
     354             : 
     355          50 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     356             :                                     FRR_PIM_AF_XPATH_VAL);
     357             : }
     358             : 
     359           0 : int pim_process_ip_pim_passive_cmd(struct vty *vty, bool enable)
     360             : {
     361           0 :         if (enable)
     362           0 :                 nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
     363             :                                       "true");
     364             :         else
     365           0 :                 nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
     366             :                                       "false");
     367             : 
     368           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     369             :                                     FRR_PIM_AF_XPATH_VAL);
     370             : }
     371             : 
     372           0 : int pim_process_no_ip_pim_cmd(struct vty *vty)
     373             : {
     374           0 :         const struct lyd_node *mld_enable_dnode;
     375           0 :         char mld_if_xpath[XPATH_MAXLEN];
     376             : 
     377           0 :         int printed =
     378           0 :                 snprintf(mld_if_xpath, sizeof(mld_if_xpath),
     379             :                          "%s/frr-gmp:gmp/address-family[address-family='%s']",
     380           0 :                          VTY_CURR_XPATH, FRR_PIM_AF_XPATH_VAL);
     381             : 
     382           0 :         if (printed >= (int)(sizeof(mld_if_xpath))) {
     383           0 :                 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
     384             :                         XPATH_MAXLEN);
     385           0 :                 return CMD_WARNING_CONFIG_FAILED;
     386             :         }
     387             : 
     388           0 :         mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
     389           0 :                                            FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
     390             :                                            FRR_PIM_AF_XPATH_VAL);
     391             : 
     392           0 :         if (!mld_enable_dnode) {
     393           0 :                 nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY, NULL);
     394           0 :                 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
     395             :         } else {
     396           0 :                 if (!yang_dnode_get_bool(mld_enable_dnode, ".")) {
     397           0 :                         nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY,
     398             :                                               NULL);
     399           0 :                         nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
     400             :                 } else
     401           0 :                         nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
     402             :                                               "false");
     403             :         }
     404             : 
     405           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     406             :                                     FRR_PIM_AF_XPATH_VAL);
     407             : }
     408             : 
     409           0 : int pim_process_ip_pim_drprio_cmd(struct vty *vty, const char *drpriority_str)
     410             : {
     411           0 :         nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
     412             :                               drpriority_str);
     413             : 
     414           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     415             :                                     FRR_PIM_AF_XPATH_VAL);
     416             : }
     417             : 
     418           0 : int pim_process_no_ip_pim_drprio_cmd(struct vty *vty)
     419             : {
     420           0 :         nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_DESTROY, NULL);
     421             : 
     422           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     423             :                                     FRR_PIM_AF_XPATH_VAL);
     424             : }
     425             : 
     426          34 : int pim_process_ip_pim_hello_cmd(struct vty *vty, const char *hello_str,
     427             :                                  const char *hold_str)
     428             : {
     429          34 :         const struct lyd_node *mld_enable_dnode;
     430             : 
     431          68 :         mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
     432          34 :                                            FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
     433             :                                            FRR_PIM_AF_XPATH_VAL);
     434             : 
     435          34 :         if (!mld_enable_dnode) {
     436          25 :                 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
     437             :                                       "true");
     438             :         } else {
     439           9 :                 if (!yang_dnode_get_bool(mld_enable_dnode, "."))
     440           0 :                         nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
     441             :                                               "true");
     442             :         }
     443             : 
     444          34 :         nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY, hello_str);
     445             : 
     446          34 :         if (hold_str)
     447          34 :                 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
     448             :                                       hold_str);
     449             : 
     450          34 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     451             :                                     FRR_PIM_AF_XPATH_VAL);
     452             : }
     453             : 
     454           0 : int pim_process_no_ip_pim_hello_cmd(struct vty *vty)
     455             : {
     456           0 :         nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_DESTROY, NULL);
     457           0 :         nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
     458             : 
     459           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     460             :                                     FRR_PIM_AF_XPATH_VAL);
     461             : }
     462             : 
     463           0 : int pim_process_ip_pim_activeactive_cmd(struct vty *vty, const char *no)
     464             : {
     465           0 :         if (no)
     466           0 :                 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
     467             :                                       "false");
     468             :         else {
     469           0 :                 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
     470             :                                       "true");
     471             : 
     472           0 :                 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
     473             :                                       "true");
     474             :         }
     475             : 
     476           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     477             :                                     FRR_PIM_AF_XPATH_VAL);
     478             : }
     479             : 
     480           0 : int pim_process_ip_pim_boundary_oil_cmd(struct vty *vty, const char *oil)
     481             : {
     482           0 :         nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
     483             :                               oil);
     484             : 
     485           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     486             :                                     FRR_PIM_AF_XPATH_VAL);
     487             : }
     488             : 
     489           0 : int pim_process_no_ip_pim_boundary_oil_cmd(struct vty *vty)
     490             : {
     491           0 :         nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
     492             :                               NULL);
     493             : 
     494           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
     495             :                                     FRR_PIM_AF_XPATH_VAL);
     496             : }
     497             : 
     498           0 : int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
     499             :                               const char *group_str, const char *source_str)
     500             : {
     501           0 :         nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, interface);
     502             : 
     503           0 :         if (!source_str) {
     504           0 :                 char buf[SRCDEST2STR_BUFFER];
     505             : 
     506           0 :                 inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
     507           0 :                 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
     508             :                                             FRR_PIM_AF_XPATH_VAL, buf,
     509             :                                             group_str);
     510             :         }
     511             : 
     512           0 :         return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
     513             :                                     FRR_PIM_AF_XPATH_VAL, source_str,
     514             :                                     group_str);
     515             : }
     516             : 
     517           0 : int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
     518             :                                  const char *group_str, const char *source_str)
     519             : {
     520           0 :         nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
     521             : 
     522           0 :         if (!source_str) {
     523           0 :                 char buf[SRCDEST2STR_BUFFER];
     524             : 
     525           0 :                 inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
     526           0 :                 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
     527             :                                             FRR_PIM_AF_XPATH_VAL, buf,
     528             :                                             group_str);
     529             :         }
     530             : 
     531           0 :         return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
     532             :                                     FRR_PIM_AF_XPATH_VAL, source_str,
     533             :                                     group_str);
     534             : }
     535             : 
     536           4 : int pim_process_rp_cmd(struct vty *vty, const char *rp_str,
     537             :                        const char *group_str)
     538             : {
     539           4 :         const char *vrfname;
     540           4 :         char rp_group_xpath[XPATH_MAXLEN];
     541           4 :         int result = 0;
     542           4 :         struct prefix group;
     543           4 :         pim_addr rp_addr;
     544             : 
     545           4 :         result = str2prefix(group_str, &group);
     546           4 :         if (result) {
     547           4 :                 struct prefix temp;
     548             : 
     549           4 :                 prefix_copy(&temp, &group);
     550           4 :                 apply_mask(&temp);
     551           4 :                 if (!prefix_same(&group, &temp)) {
     552           0 :                         vty_out(vty, "%% Inconsistent address and mask: %s\n",
     553             :                                 group_str);
     554           0 :                         return CMD_WARNING_CONFIG_FAILED;
     555             :                 }
     556             :         }
     557             : 
     558           4 :         if (!result) {
     559           0 :                 vty_out(vty, "%% Bad group address specified: %s\n", group_str);
     560           0 :                 return CMD_WARNING_CONFIG_FAILED;
     561             :         }
     562             : 
     563           4 :         result = inet_pton(PIM_AF, rp_str, &rp_addr);
     564           4 :         if (result <= 0) {
     565           0 :                 vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
     566           0 :                 return CMD_WARNING_CONFIG_FAILED;
     567             :         }
     568             : 
     569           4 :         if (pim_addr_is_any(rp_addr) || pim_addr_is_multicast(rp_addr)) {
     570           0 :                 vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
     571           0 :                 return CMD_WARNING_CONFIG_FAILED;
     572             :         }
     573             : 
     574             : #if PIM_IPV == 6
     575           2 :         if (IN6_IS_ADDR_LINKLOCAL(&rp_addr)) {
     576           0 :                 vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
     577           0 :                 return CMD_WARNING_CONFIG_FAILED;
     578             :         }
     579             : #endif
     580             : 
     581           4 :         vrfname = pim_cli_get_vrf_name(vty);
     582           4 :         if (vrfname == NULL)
     583             :                 return CMD_WARNING_CONFIG_FAILED;
     584             : 
     585           4 :         snprintf(rp_group_xpath, sizeof(rp_group_xpath),
     586             :                  FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
     587             :                  FRR_PIM_AF_XPATH_VAL, rp_str);
     588           4 :         strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
     589             : 
     590           4 :         nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
     591             : 
     592           4 :         return nb_cli_apply_changes(vty, NULL);
     593             : }
     594             : 
     595           0 : int pim_process_no_rp_cmd(struct vty *vty, const char *rp_str,
     596             :                           const char *group_str)
     597             : {
     598           0 :         char group_list_xpath[XPATH_MAXLEN];
     599           0 :         char group_xpath[XPATH_MAXLEN];
     600           0 :         char rp_xpath[XPATH_MAXLEN];
     601           0 :         int printed;
     602           0 :         const char *vrfname;
     603           0 :         const struct lyd_node *group_dnode;
     604             : 
     605           0 :         vrfname = pim_cli_get_vrf_name(vty);
     606           0 :         if (vrfname == NULL)
     607             :                 return CMD_WARNING_CONFIG_FAILED;
     608             : 
     609           0 :         snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
     610             :                  "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
     611             : 
     612           0 :         printed = snprintf(group_list_xpath, sizeof(group_list_xpath),
     613             :                            "%s/group-list", rp_xpath);
     614             : 
     615           0 :         if (printed >= (int)(sizeof(group_list_xpath))) {
     616           0 :                 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
     617             :                         XPATH_MAXLEN);
     618           0 :                 return CMD_WARNING_CONFIG_FAILED;
     619             :         }
     620             : 
     621           0 :         printed = snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
     622             :                            group_list_xpath, group_str);
     623             : 
     624           0 :         if (printed >= (int)(sizeof(group_xpath))) {
     625           0 :                 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
     626             :                         XPATH_MAXLEN);
     627           0 :                 return CMD_WARNING_CONFIG_FAILED;
     628             :         }
     629             : 
     630           0 :         group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
     631           0 :         if (!group_dnode) {
     632           0 :                 vty_out(vty, "%% Unable to find specified RP\n");
     633           0 :                 return NB_OK;
     634             :         }
     635             : 
     636           0 :         if (yang_is_last_list_dnode(group_dnode))
     637           0 :                 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
     638             :         else
     639           0 :                 nb_cli_enqueue_change(vty, group_list_xpath, NB_OP_DESTROY,
     640             :                                       group_str);
     641             : 
     642           0 :         return nb_cli_apply_changes(vty, NULL);
     643             : }
     644             : 
     645           0 : int pim_process_rp_plist_cmd(struct vty *vty, const char *rp_str,
     646             :                              const char *prefix_list)
     647             : {
     648           0 :         const char *vrfname;
     649           0 :         char rp_plist_xpath[XPATH_MAXLEN];
     650             : 
     651           0 :         vrfname = pim_cli_get_vrf_name(vty);
     652           0 :         if (vrfname == NULL)
     653             :                 return CMD_WARNING_CONFIG_FAILED;
     654             : 
     655           0 :         snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
     656             :                  FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
     657             :                  FRR_PIM_AF_XPATH_VAL, rp_str);
     658           0 :         strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
     659             : 
     660           0 :         nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY, prefix_list);
     661             : 
     662           0 :         return nb_cli_apply_changes(vty, NULL);
     663             : }
     664             : 
     665           0 : int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
     666             :                                 const char *prefix_list)
     667             : {
     668           0 :         char rp_xpath[XPATH_MAXLEN];
     669           0 :         char plist_xpath[XPATH_MAXLEN];
     670           0 :         const char *vrfname;
     671           0 :         const struct lyd_node *plist_dnode;
     672           0 :         const char *plist;
     673             : 
     674           0 :         vrfname = pim_cli_get_vrf_name(vty);
     675           0 :         if (vrfname == NULL)
     676             :                 return CMD_WARNING_CONFIG_FAILED;
     677             : 
     678           0 :         snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
     679             :                  "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
     680             : 
     681           0 :         snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
     682             :                  "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
     683           0 :         strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
     684             : 
     685           0 :         plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
     686           0 :         if (!plist_dnode) {
     687           0 :                 vty_out(vty, "%% Unable to find specified RP\n");
     688           0 :                 return NB_OK;
     689             :         }
     690             : 
     691           0 :         plist = yang_dnode_get_string(plist_dnode, "%s", plist_xpath);
     692           0 :         if (strcmp(prefix_list, plist)) {
     693           0 :                 vty_out(vty, "%% Unable to find specified RP\n");
     694           0 :                 return NB_OK;
     695             :         }
     696             : 
     697           0 :         nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
     698             : 
     699           0 :         return nb_cli_apply_changes(vty, NULL);
     700             : }
     701             : 
     702          25 : bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
     703             : {
     704          25 :         return (pim_addr_is_any(match.grp) ||
     705          25 :                 !pim_addr_cmp(match.grp, item.grp)) &&
     706          25 :                (pim_addr_is_any(match.src) ||
     707           0 :                 !pim_addr_cmp(match.src, item.src));
     708             : }
     709             : 
     710          17 : void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
     711             : {
     712          17 :         struct pim_interface *pim_ifp;
     713             : 
     714          17 :         pim_ifp = ifp->info;
     715          17 :         json_object_string_add(json, "name", ifp->name);
     716          17 :         json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
     717          17 :         json_object_string_addf(json, "address", "%pPA",
     718             :                                 &pim_ifp->primary_address);
     719          17 :         json_object_int_add(json, "index", ifp->ifindex);
     720             : 
     721          17 :         if (if_is_multicast(ifp))
     722          17 :                 json_object_boolean_true_add(json, "flagMulticast");
     723             : 
     724          17 :         if (if_is_broadcast(ifp))
     725          17 :                 json_object_boolean_true_add(json, "flagBroadcast");
     726             : 
     727          17 :         if (ifp->flags & IFF_ALLMULTI)
     728           0 :                 json_object_boolean_true_add(json, "flagAllMulticast");
     729             : 
     730          17 :         if (ifp->flags & IFF_PROMISC)
     731           0 :                 json_object_boolean_true_add(json, "flagPromiscuous");
     732             : 
     733          17 :         if (PIM_IF_IS_DELETED(ifp))
     734           0 :                 json_object_boolean_true_add(json, "flagDeleted");
     735             : 
     736          17 :         if (pim_if_lan_delay_enabled(ifp))
     737          17 :                 json_object_boolean_true_add(json, "lanDelayEnabled");
     738          17 : }
     739             : 
     740           0 : void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
     741             : {
     742           0 :         vty_out(vty, "Flags\n");
     743           0 :         vty_out(vty, "-----\n");
     744           0 :         vty_out(vty, "All Multicast   : %s\n",
     745           0 :                 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
     746           0 :         vty_out(vty, "Broadcast       : %s\n",
     747           0 :                 if_is_broadcast(ifp) ? "yes" : "no");
     748           0 :         vty_out(vty, "Deleted         : %s\n",
     749           0 :                 PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
     750           0 :         vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
     751           0 :         vty_out(vty, "Multicast       : %s\n",
     752           0 :                 if_is_multicast(ifp) ? "yes" : "no");
     753           0 :         vty_out(vty, "Promiscuous     : %s\n",
     754           0 :                 (ifp->flags & IFF_PROMISC) ? "yes" : "no");
     755           0 :         vty_out(vty, "\n");
     756           0 :         vty_out(vty, "\n");
     757           0 : }
     758             : 
     759           8 : void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
     760             : {
     761           8 :         json_object_boolean_add(
     762             :                 json, "drJoinDesired",
     763           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED));
     764           8 :         json_object_boolean_add(
     765             :                 json, "drJoinDesiredUpdated",
     766           8 :                 CHECK_FLAG(up->flags,
     767             :                            PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED));
     768           8 :         json_object_boolean_add(
     769             :                 json, "firstHopRouter",
     770           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FHR));
     771           8 :         json_object_boolean_add(
     772             :                 json, "sourceIgmp",
     773           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP));
     774           8 :         json_object_boolean_add(
     775             :                 json, "sourcePim",
     776           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_PIM));
     777           8 :         json_object_boolean_add(
     778             :                 json, "sourceStream",
     779           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM));
     780             :         /* XXX: need to print ths flag in the plain text display as well */
     781           8 :         json_object_boolean_add(
     782             :                 json, "sourceMsdp",
     783           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP));
     784           8 :         json_object_boolean_add(
     785             :                 json, "sendSGRptPrune",
     786           8 :                 CHECK_FLAG(up->flags,
     787             :                            PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE));
     788           8 :         json_object_boolean_add(
     789             :                 json, "lastHopRouter",
     790           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_LHR));
     791           8 :         json_object_boolean_add(
     792             :                 json, "disableKATExpiry",
     793           8 :                 CHECK_FLAG(up->flags,
     794             :                            PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY));
     795           8 :         json_object_boolean_add(
     796             :                 json, "staticIncomingInterface",
     797           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF));
     798           8 :         json_object_boolean_add(
     799             :                 json, "allowIncomingInterfaceinOil",
     800           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL));
     801           8 :         json_object_boolean_add(
     802             :                 json, "noPimRegistrationData",
     803           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA));
     804           8 :         json_object_boolean_add(
     805             :                 json, "forcePimRegistration",
     806           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG));
     807           8 :         json_object_boolean_add(
     808             :                 json, "sourceVxlanOrigination",
     809           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG));
     810           8 :         json_object_boolean_add(
     811             :                 json, "sourceVxlanTermination",
     812           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM));
     813           8 :         json_object_boolean_add(
     814             :                 json, "mlagVxlan",
     815           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN));
     816           8 :         json_object_boolean_add(
     817             :                 json, "mlagNonDesignatedForwarder",
     818           8 :                 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF));
     819           8 : }
     820             : 
     821             : static const char *
     822           8 : pim_upstream_state2brief_str(enum pim_upstream_state join_state,
     823             :                              char *state_str, size_t state_str_len)
     824             : {
     825           8 :         switch (join_state) {
     826           7 :         case PIM_UPSTREAM_NOTJOINED:
     827           7 :                 strlcpy(state_str, "NotJ", state_str_len);
     828           7 :                 break;
     829           1 :         case PIM_UPSTREAM_JOINED:
     830           1 :                 strlcpy(state_str, "J", state_str_len);
     831           1 :                 break;
     832           0 :         default:
     833           0 :                 strlcpy(state_str, "Unk", state_str_len);
     834             :         }
     835           8 :         return state_str;
     836             : }
     837             : 
     838           6 : static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
     839             :                                            char *state_str,
     840             :                                            size_t state_str_len)
     841             : {
     842           6 :         switch (reg_state) {
     843           0 :         case PIM_REG_NOINFO:
     844           0 :                 strlcpy(state_str, "RegNI", state_str_len);
     845           0 :                 break;
     846           0 :         case PIM_REG_JOIN:
     847           0 :                 strlcpy(state_str, "RegJ", state_str_len);
     848           0 :                 break;
     849           6 :         case PIM_REG_JOIN_PENDING:
     850             :         case PIM_REG_PRUNE:
     851           6 :                 strlcpy(state_str, "RegP", state_str_len);
     852           6 :                 break;
     853             :         }
     854           6 :         return state_str;
     855             : }
     856             : 
     857           0 : void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
     858             :                                 time_t now, json_object *json)
     859             : {
     860           0 :         char refresh_uptime[10];
     861             : 
     862           0 :         pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
     863             :                               pim->rpf_cache_refresh_last);
     864             : 
     865           0 :         if (json) {
     866           0 :                 json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
     867           0 :                                     router->rpf_cache_refresh_delay_msec);
     868           0 :                 json_object_int_add(
     869             :                         json, "rpfCacheRefreshTimer",
     870             :                         pim_time_timer_remain_msec(pim->rpf_cache_refresher));
     871           0 :                 json_object_int_add(json, "rpfCacheRefreshRequests",
     872             :                                     pim->rpf_cache_refresh_requests);
     873           0 :                 json_object_int_add(json, "rpfCacheRefreshEvents",
     874             :                                     pim->rpf_cache_refresh_events);
     875           0 :                 json_object_string_add(json, "rpfCacheRefreshLast",
     876             :                                        refresh_uptime);
     877           0 :                 json_object_int_add(json, "nexthopLookups",
     878             :                                     pim->nexthop_lookups);
     879           0 :                 json_object_int_add(json, "nexthopLookupsAvoided",
     880             :                                     pim->nexthop_lookups_avoided);
     881             :         } else {
     882           0 :                 vty_out(vty,
     883             :                         "RPF Cache Refresh Delay:    %ld msecs\n"
     884             :                         "RPF Cache Refresh Timer:    %ld msecs\n"
     885             :                         "RPF Cache Refresh Requests: %lld\n"
     886             :                         "RPF Cache Refresh Events:   %lld\n"
     887             :                         "RPF Cache Refresh Last:     %s\n"
     888             :                         "Nexthop Lookups:            %lld\n"
     889             :                         "Nexthop Lookups Avoided:    %lld\n",
     890           0 :                         router->rpf_cache_refresh_delay_msec,
     891             :                         pim_time_timer_remain_msec(pim->rpf_cache_refresher),
     892           0 :                         (long long)pim->rpf_cache_refresh_requests,
     893           0 :                         (long long)pim->rpf_cache_refresh_events,
     894           0 :                         refresh_uptime, (long long)pim->nexthop_lookups,
     895           0 :                         (long long)pim->nexthop_lookups_avoided);
     896             :         }
     897           0 : }
     898             : 
     899           0 : void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
     900             : {
     901           0 :         struct pim_upstream *up;
     902           0 :         time_t now = pim_time_monotonic_sec();
     903           0 :         struct ttable *tt = NULL;
     904           0 :         char *table = NULL;
     905           0 :         json_object *json_group = NULL;
     906           0 :         json_object *json_row = NULL;
     907             : 
     908           0 :         pim_show_rpf_refresh_stats(vty, pim, now, json);
     909             : 
     910           0 :         if (!json) {
     911           0 :                 vty_out(vty, "\n");
     912             : 
     913             :                 /* Prepare table. */
     914           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
     915           0 :                 ttable_add_row(
     916             :                         tt,
     917             :                         "Source|Group|RpfIface|RpfAddress|RibNextHop|Metric|Pref");
     918           0 :                 tt->style.cell.rpad = 2;
     919           0 :                 tt->style.corner = '+';
     920           0 :                 ttable_restyle(tt);
     921             :         }
     922             : 
     923           0 :         frr_each (rb_pim_upstream, &pim->upstream_head, up) {
     924           0 :                 const char *rpf_ifname;
     925           0 :                 struct pim_rpf *rpf = &up->rpf;
     926             : 
     927           0 :                 rpf_ifname =
     928           0 :                         rpf->source_nexthop.interface ? rpf->source_nexthop
     929             :                                                                 .interface->name
     930           0 :                                                       : "<ifname?>";
     931             : 
     932           0 :                 if (json) {
     933           0 :                         char grp_str[PIM_ADDRSTRLEN];
     934           0 :                         char src_str[PIM_ADDRSTRLEN];
     935             : 
     936           0 :                         snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
     937             :                                    &up->sg.grp);
     938           0 :                         snprintfrr(src_str, sizeof(src_str), "%pPAs",
     939             :                                    &up->sg.src);
     940             : 
     941           0 :                         json_object_object_get_ex(json, grp_str, &json_group);
     942             : 
     943           0 :                         if (!json_group) {
     944           0 :                                 json_group = json_object_new_object();
     945           0 :                                 json_object_object_add(json, grp_str,
     946             :                                                        json_group);
     947             :                         }
     948             : 
     949           0 :                         json_row = json_object_new_object();
     950           0 :                         json_object_string_add(json_row, "source", src_str);
     951           0 :                         json_object_string_add(json_row, "group", grp_str);
     952           0 :                         json_object_string_add(json_row, "rpfInterface",
     953             :                                                rpf_ifname);
     954           0 :                         json_object_string_addf(json_row, "rpfAddress", "%pPA",
     955             :                                                 &rpf->rpf_addr);
     956           0 :                         json_object_string_addf(
     957             :                                 json_row, "ribNexthop", "%pPAs",
     958             :                                 &rpf->source_nexthop.mrib_nexthop_addr);
     959           0 :                         json_object_int_add(
     960             :                                 json_row, "routeMetric",
     961           0 :                                 rpf->source_nexthop.mrib_route_metric);
     962           0 :                         json_object_int_add(
     963             :                                 json_row, "routePreference",
     964           0 :                                 rpf->source_nexthop.mrib_metric_preference);
     965           0 :                         json_object_object_add(json_group, src_str, json_row);
     966             : 
     967             :                 } else {
     968           0 :                         ttable_add_row(
     969             :                                 tt, "%pPAs|%pPAs|%s|%pPA|%pPAs|%d|%d",
     970             :                                 &up->sg.src, &up->sg.grp, rpf_ifname,
     971             :                                 &rpf->rpf_addr,
     972             :                                 &rpf->source_nexthop.mrib_nexthop_addr,
     973             :                                 rpf->source_nexthop.mrib_route_metric,
     974             :                                 rpf->source_nexthop.mrib_metric_preference);
     975             :                 }
     976             :         }
     977             :         /* Dump the generated table. */
     978           0 :         if (!json) {
     979           0 :                 table = ttable_dump(tt, "\n");
     980           0 :                 vty_out(vty, "%s\n", table);
     981           0 :                 XFREE(MTYPE_TMP, table);
     982           0 :                 ttable_del(tt);
     983             :         }
     984           0 : }
     985             : 
     986           0 : void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
     987             : {
     988           0 :         struct interface *ifp;
     989           0 :         struct ttable *tt = NULL;
     990           0 :         char *table = NULL;
     991             : 
     992             :         /* Prepare table. */
     993           0 :         tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
     994           0 :         ttable_add_row(tt, "Interface|Address|Neighbor|Secondary");
     995           0 :         tt->style.cell.rpad = 2;
     996           0 :         tt->style.corner = '+';
     997           0 :         ttable_restyle(tt);
     998             : 
     999           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    1000           0 :                 struct pim_interface *pim_ifp;
    1001           0 :                 pim_addr ifaddr;
    1002           0 :                 struct listnode *neighnode;
    1003           0 :                 struct pim_neighbor *neigh;
    1004             : 
    1005           0 :                 pim_ifp = ifp->info;
    1006             : 
    1007           0 :                 if (!pim_ifp)
    1008           0 :                         continue;
    1009             : 
    1010           0 :                 if (pim_ifp->pim_sock_fd < 0)
    1011           0 :                         continue;
    1012             : 
    1013           0 :                 ifaddr = pim_ifp->primary_address;
    1014             : 
    1015           0 :                 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
    1016             :                                           neigh)) {
    1017           0 :                         struct listnode *prefix_node;
    1018           0 :                         struct prefix *p;
    1019             : 
    1020           0 :                         if (!neigh->prefix_list)
    1021           0 :                                 continue;
    1022             : 
    1023           0 :                         for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
    1024             :                                                   prefix_node, p))
    1025           0 :                                 ttable_add_row(tt, "%s|%pPAs|%pPAs|%pFX",
    1026           0 :                                                ifp->name, &ifaddr,
    1027             :                                                &neigh->source_addr, p);
    1028             :                 }
    1029             :         }
    1030             :         /* Dump the generated table. */
    1031           0 :         table = ttable_dump(tt, "\n");
    1032           0 :         vty_out(vty, "%s\n", table);
    1033           0 :         XFREE(MTYPE_TMP, table);
    1034           0 :         ttable_del(tt);
    1035           0 : }
    1036             : 
    1037           0 : void pim_show_state(struct pim_instance *pim, struct vty *vty,
    1038             :                     const char *src_or_group, const char *group,
    1039             :                     json_object *json)
    1040             : {
    1041           0 :         struct channel_oil *c_oil;
    1042             : #if PIM_IPV != 4
    1043           0 :         struct ttable *tt = NULL;
    1044           0 :         char *table = NULL;
    1045             : #endif
    1046           0 :         char flag[50];
    1047           0 :         json_object *json_group = NULL;
    1048           0 :         json_object *json_ifp_in = NULL;
    1049           0 :         json_object *json_ifp_out = NULL;
    1050           0 :         json_object *json_source = NULL;
    1051           0 :         time_t now;
    1052           0 :         int first_oif;
    1053             : 
    1054           0 :         now = pim_time_monotonic_sec();
    1055             : 
    1056           0 :         if (!json) {
    1057           0 :                 vty_out(vty,
    1058             :                         "Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted\n");
    1059             : #if PIM_IPV == 4
    1060           0 :                 vty_out(vty,
    1061             :                         "Active Source           Group            RPT  IIF               OIL\n");
    1062             : #else
    1063             :                 /* Prepare table. */
    1064           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    1065           0 :                 ttable_add_row(tt, "Active|Source|Group|RPT|IIF|OIL");
    1066           0 :                 tt->style.cell.rpad = 2;
    1067           0 :                 tt->style.corner = '+';
    1068           0 :                 ttable_restyle(tt);
    1069             : #endif
    1070             :         }
    1071             : 
    1072           0 :         frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
    1073           0 :                 char src_str[PIM_ADDRSTRLEN];
    1074           0 :                 char grp_str[PIM_ADDRSTRLEN];
    1075           0 :                 char in_ifname[INTERFACE_NAMSIZ + 1];
    1076           0 :                 char out_ifname[INTERFACE_NAMSIZ + 1];
    1077           0 :                 int oif_vif_index;
    1078           0 :                 struct interface *ifp_in;
    1079           0 :                 bool isRpt;
    1080             : 
    1081           0 :                 first_oif = 1;
    1082             : 
    1083           0 :                 if ((c_oil->up &&
    1084           0 :                      PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
    1085           0 :                     pim_addr_is_any(*oil_origin(c_oil)))
    1086             :                         isRpt = true;
    1087             :                 else
    1088             :                         isRpt = false;
    1089             : 
    1090           0 :                 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
    1091             :                            oil_mcastgrp(c_oil));
    1092           0 :                 snprintfrr(src_str, sizeof(src_str), "%pPAs",
    1093             :                            oil_origin(c_oil));
    1094           0 :                 ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
    1095             : 
    1096           0 :                 if (ifp_in)
    1097           0 :                         strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
    1098             :                 else
    1099           0 :                         strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
    1100             : 
    1101           0 :                 if (src_or_group) {
    1102           0 :                         if (strcmp(src_or_group, src_str) &&
    1103           0 :                             strcmp(src_or_group, grp_str))
    1104           0 :                                 continue;
    1105             : 
    1106           0 :                         if (group && strcmp(group, grp_str))
    1107           0 :                                 continue;
    1108             :                 }
    1109             : 
    1110           0 :                 if (json) {
    1111             : 
    1112             :                         /* Find the group, create it if it doesn't exist */
    1113           0 :                         json_object_object_get_ex(json, grp_str, &json_group);
    1114             : 
    1115           0 :                         if (!json_group) {
    1116           0 :                                 json_group = json_object_new_object();
    1117           0 :                                 json_object_object_add(json, grp_str,
    1118             :                                                        json_group);
    1119             :                         }
    1120             : 
    1121             :                         /* Find the source nested under the group, create it if
    1122             :                          * it doesn't exist
    1123             :                          */
    1124           0 :                         json_object_object_get_ex(json_group, src_str,
    1125             :                                                   &json_source);
    1126             : 
    1127           0 :                         if (!json_source) {
    1128           0 :                                 json_source = json_object_new_object();
    1129           0 :                                 json_object_object_add(json_group, src_str,
    1130             :                                                        json_source);
    1131             :                         }
    1132             : 
    1133             :                         /* Find the inbound interface nested under the source,
    1134             :                          * create it if it doesn't exist
    1135             :                          */
    1136           0 :                         json_object_object_get_ex(json_source, in_ifname,
    1137             :                                                   &json_ifp_in);
    1138             : 
    1139           0 :                         if (!json_ifp_in) {
    1140           0 :                                 json_ifp_in = json_object_new_object();
    1141           0 :                                 json_object_object_add(json_source, in_ifname,
    1142             :                                                        json_ifp_in);
    1143           0 :                                 json_object_int_add(json_source, "installed",
    1144           0 :                                                     c_oil->installed);
    1145           0 :                                 json_object_boolean_add(json_source, "isRpt",
    1146             :                                                         isRpt);
    1147           0 :                                 json_object_int_add(json_source, "refCount",
    1148           0 :                                                     c_oil->oil_ref_count);
    1149           0 :                                 json_object_int_add(json_source, "oilListSize",
    1150           0 :                                                     c_oil->oil_size);
    1151           0 :                                 json_object_int_add(
    1152             :                                         json_source, "oilRescan",
    1153           0 :                                         c_oil->oil_inherited_rescan);
    1154           0 :                                 json_object_int_add(json_source, "lastUsed",
    1155           0 :                                                     c_oil->cc.lastused);
    1156           0 :                                 json_object_int_add(json_source, "packetCount",
    1157           0 :                                                     c_oil->cc.pktcnt);
    1158           0 :                                 json_object_int_add(json_source, "byteCount",
    1159           0 :                                                     c_oil->cc.bytecnt);
    1160           0 :                                 json_object_int_add(json_source,
    1161             :                                                     "wrongInterface",
    1162           0 :                                                     c_oil->cc.wrong_if);
    1163             :                         }
    1164             :                 }
    1165             : #if PIM_IPV == 4
    1166             :                 else
    1167           0 :                         vty_out(vty, "%-6d %-15pPAs  %-15pPAs  %-3s  %-16s  ",
    1168             :                                 c_oil->installed, oil_origin(c_oil),
    1169             :                                 oil_mcastgrp(c_oil), isRpt ? "y" : "n",
    1170             :                                 in_ifname);
    1171             : #endif
    1172             : 
    1173           0 :                 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
    1174           0 :                      ++oif_vif_index) {
    1175           0 :                         struct interface *ifp_out;
    1176           0 :                         char oif_uptime[10];
    1177           0 :                         int ttl;
    1178             : 
    1179           0 :                         ttl = oil_if_has(c_oil, oif_vif_index);
    1180           0 :                         if (ttl < 1)
    1181           0 :                                 continue;
    1182             : 
    1183           0 :                         ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
    1184           0 :                         pim_time_uptime(
    1185             :                                 oif_uptime, sizeof(oif_uptime),
    1186           0 :                                 now - c_oil->oif_creation[oif_vif_index]);
    1187             : 
    1188           0 :                         if (ifp_out)
    1189           0 :                                 strlcpy(out_ifname, ifp_out->name,
    1190             :                                         sizeof(out_ifname));
    1191             :                         else
    1192           0 :                                 strlcpy(out_ifname, "<oif?>",
    1193             :                                         sizeof(out_ifname));
    1194             : 
    1195           0 :                         if (json) {
    1196           0 :                                 json_ifp_out = json_object_new_object();
    1197           0 :                                 json_object_string_add(json_ifp_out, "source",
    1198             :                                                        src_str);
    1199           0 :                                 json_object_string_add(json_ifp_out, "group",
    1200             :                                                        grp_str);
    1201           0 :                                 json_object_string_add(json_ifp_out,
    1202             :                                                        "inboundInterface",
    1203             :                                                        in_ifname);
    1204           0 :                                 json_object_string_add(json_ifp_out,
    1205             :                                                        "outboundInterface",
    1206             :                                                        out_ifname);
    1207           0 :                                 json_object_int_add(json_ifp_out, "installed",
    1208           0 :                                                     c_oil->installed);
    1209             : 
    1210           0 :                                 json_object_object_add(json_ifp_in, out_ifname,
    1211             :                                                        json_ifp_out);
    1212             :                         } else {
    1213           0 :                                 flag[0] = '\0';
    1214           0 :                                 snprintf(flag, sizeof(flag), "(%c%c%c%c%c)",
    1215           0 :                                          (c_oil->oif_flags[oif_vif_index] &
    1216             :                                           PIM_OIF_FLAG_PROTO_GM)
    1217             :                                                  ? 'I'
    1218             :                                                  : ' ',
    1219           0 :                                          (c_oil->oif_flags[oif_vif_index] &
    1220             :                                           PIM_OIF_FLAG_PROTO_PIM)
    1221             :                                                  ? 'J'
    1222             :                                                  : ' ',
    1223           0 :                                          (c_oil->oif_flags[oif_vif_index] &
    1224             :                                           PIM_OIF_FLAG_PROTO_VXLAN)
    1225             :                                                  ? 'V'
    1226             :                                                  : ' ',
    1227           0 :                                          (c_oil->oif_flags[oif_vif_index] &
    1228             :                                           PIM_OIF_FLAG_PROTO_STAR)
    1229             :                                                  ? '*'
    1230             :                                                  : ' ',
    1231           0 :                                          (c_oil->oif_flags[oif_vif_index] &
    1232             :                                           PIM_OIF_FLAG_MUTE)
    1233             :                                                  ? 'M'
    1234             :                                                  : ' ');
    1235             : 
    1236           0 :                                 if (first_oif) {
    1237           0 :                                         first_oif = 0;
    1238             : #if PIM_IPV == 4
    1239           0 :                                         vty_out(vty, "%s%s", out_ifname, flag);
    1240             : #else
    1241           0 :                                         ttable_add_row(
    1242             :                                                 tt, "%d|%pPAs|%pPAs|%s|%s|%s%s",
    1243             :                                                 c_oil->installed,
    1244             :                                                 oil_origin(c_oil),
    1245             :                                                 oil_mcastgrp(c_oil),
    1246             :                                                 isRpt ? "y" : "n", in_ifname,
    1247             :                                                 out_ifname, flag);
    1248             : #endif
    1249             :                                 } else {
    1250             : #if PIM_IPV == 4
    1251           0 :                                         vty_out(vty, ", %s%s", out_ifname,
    1252             :                                                 flag);
    1253             : #else
    1254           0 :                                         ttable_add_row(tt,
    1255             :                                                        "%c|%c|%c|%c|%c|%s%s",
    1256             :                                                        ' ', ' ', ' ', ' ', ' ',
    1257             :                                                        out_ifname, flag);
    1258             : #endif
    1259             :                                 }
    1260             :                         }
    1261             :                 }
    1262             : #if PIM_IPV == 4
    1263           0 :                 if (!json)
    1264           0 :                         vty_out(vty, "\n");
    1265             : #endif
    1266             :         }
    1267             : 
    1268             :         /* Dump the generated table. */
    1269           0 :         if (!json) {
    1270             : #if PIM_IPV == 4
    1271           0 :                 vty_out(vty, "\n");
    1272             : #else
    1273           0 :                 table = ttable_dump(tt, "\n");
    1274           0 :                 vty_out(vty, "%s\n", table);
    1275           0 :                 XFREE(MTYPE_TMP, table);
    1276           0 :                 ttable_del(tt);
    1277             : #endif
    1278             :         }
    1279           0 : }
    1280             : 
    1281             : /* pim statistics - just adding only bsm related now.
    1282             :  * We can continue to add all pim related stats here.
    1283             :  */
    1284           0 : void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
    1285             :                          const char *ifname, bool uj)
    1286             : {
    1287           0 :         json_object *json = NULL;
    1288           0 :         struct interface *ifp;
    1289             : 
    1290           0 :         if (uj) {
    1291           0 :                 json = json_object_new_object();
    1292           0 :                 json_object_int_add(json, "bsmRx", pim->bsm_rcvd);
    1293           0 :                 json_object_int_add(json, "bsmTx", pim->bsm_sent);
    1294           0 :                 json_object_int_add(json, "bsmDropped", pim->bsm_dropped);
    1295             :         } else {
    1296           0 :                 vty_out(vty, "BSM Statistics :\n");
    1297           0 :                 vty_out(vty, "----------------\n");
    1298           0 :                 vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
    1299             :                         pim->bsm_rcvd);
    1300           0 :                 vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
    1301             :                         pim->bsm_sent);
    1302           0 :                 vty_out(vty, "Number of Dropped BSMs  : %" PRIu64 "\n",
    1303             :                         pim->bsm_dropped);
    1304             :         }
    1305             : 
    1306           0 :         vty_out(vty, "\n");
    1307             : 
    1308             :         /* scan interfaces */
    1309           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    1310           0 :                 struct pim_interface *pim_ifp = ifp->info;
    1311             : 
    1312           0 :                 if (ifname && strcmp(ifname, ifp->name))
    1313           0 :                         continue;
    1314             : 
    1315           0 :                 if (!pim_ifp)
    1316           0 :                         continue;
    1317             : 
    1318           0 :                 if (!uj) {
    1319           0 :                         vty_out(vty, "Interface : %s\n", ifp->name);
    1320           0 :                         vty_out(vty, "-------------------\n");
    1321           0 :                         vty_out(vty,
    1322             :                                 "Number of BSMs dropped due to config miss : %u\n",
    1323             :                                 pim_ifp->pim_ifstat_bsm_cfg_miss);
    1324           0 :                         vty_out(vty, "Number of unicast BSMs dropped : %u\n",
    1325             :                                 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
    1326           0 :                         vty_out(vty,
    1327             :                                 "Number of BSMs dropped due to invalid scope zone : %u\n",
    1328             :                                 pim_ifp->pim_ifstat_bsm_invalid_sz);
    1329             :                 } else {
    1330             : 
    1331           0 :                         json_object *json_row = NULL;
    1332             : 
    1333           0 :                         json_row = json_object_new_object();
    1334             : 
    1335           0 :                         json_object_string_add(json_row, "If Name", ifp->name);
    1336           0 :                         json_object_int_add(json_row, "bsmDroppedConfig",
    1337           0 :                                             pim_ifp->pim_ifstat_bsm_cfg_miss);
    1338           0 :                         json_object_int_add(
    1339             :                                 json_row, "bsmDroppedUnicast",
    1340           0 :                                 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
    1341           0 :                         json_object_int_add(json_row,
    1342             :                                             "bsmDroppedInvalidScopeZone",
    1343           0 :                                             pim_ifp->pim_ifstat_bsm_invalid_sz);
    1344           0 :                         json_object_object_add(json, ifp->name, json_row);
    1345             :                 }
    1346           0 :                 vty_out(vty, "\n");
    1347             :         }
    1348             : 
    1349           0 :         if (uj)
    1350           0 :                 vty_json(vty, json);
    1351           0 : }
    1352             : 
    1353           4 : void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
    1354             :                        pim_sgaddr *sg, json_object *json)
    1355             : {
    1356           4 :         struct pim_upstream *up;
    1357           4 :         struct ttable *tt = NULL;
    1358           4 :         char *table = NULL;
    1359           4 :         time_t now;
    1360           4 :         json_object *json_group = NULL;
    1361           4 :         json_object *json_row = NULL;
    1362             : 
    1363           4 :         now = pim_time_monotonic_sec();
    1364             : 
    1365           4 :         if (!json) {
    1366             :                 /* Prepare table. */
    1367           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    1368           0 :                 ttable_add_row(
    1369             :                         tt,
    1370             :                         "Iif|Source|Group|State|Uptime|JoinTimer|RSTimer|KATimer|RefCnt");
    1371           0 :                 tt->style.cell.rpad = 2;
    1372           0 :                 tt->style.corner = '+';
    1373           0 :                 ttable_restyle(tt);
    1374             :         }
    1375             : 
    1376          24 :         frr_each (rb_pim_upstream, &pim->upstream_head, up) {
    1377           8 :                 char uptime[10];
    1378           8 :                 char join_timer[10];
    1379           8 :                 char rs_timer[10];
    1380           8 :                 char ka_timer[10];
    1381           8 :                 char msdp_reg_timer[10];
    1382           8 :                 char state_str[PIM_REG_STATE_STR_LEN];
    1383             : 
    1384           8 :                 if (!pim_sgaddr_match(up->sg, *sg))
    1385           0 :                         continue;
    1386             : 
    1387           8 :                 pim_time_uptime(uptime, sizeof(uptime),
    1388           8 :                                 now - up->state_transition);
    1389           8 :                 pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
    1390             :                                          up->t_join_timer);
    1391             : 
    1392             :                 /*
    1393             :                  * If the upstream is not dummy and it has a J/P timer for the
    1394             :                  * neighbor display that
    1395             :                  */
    1396           8 :                 if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
    1397           8 :                         struct pim_neighbor *nbr;
    1398             : 
    1399           8 :                         nbr = pim_neighbor_find(
    1400             :                                 up->rpf.source_nexthop.interface,
    1401             :                                 up->rpf.rpf_addr);
    1402           8 :                         if (nbr)
    1403           2 :                                 pim_time_timer_to_hhmmss(join_timer,
    1404             :                                                          sizeof(join_timer),
    1405             :                                                          nbr->jp_timer);
    1406             :                 }
    1407             : 
    1408           8 :                 pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
    1409             :                                          up->t_rs_timer);
    1410           8 :                 pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
    1411             :                                          up->t_ka_timer);
    1412           8 :                 pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
    1413             :                                          up->t_msdp_reg_timer);
    1414             : 
    1415           8 :                 pim_upstream_state2brief_str(up->join_state, state_str,
    1416             :                                              sizeof(state_str));
    1417           8 :                 if (up->reg_state != PIM_REG_NOINFO) {
    1418           6 :                         char tmp_str[PIM_REG_STATE_STR_LEN];
    1419           6 :                         char tmp[sizeof(state_str) + 1];
    1420             : 
    1421           6 :                         snprintf(tmp, sizeof(tmp), ",%s",
    1422             :                                  pim_reg_state2brief_str(up->reg_state, tmp_str,
    1423             :                                                          sizeof(tmp_str)));
    1424           6 :                         strlcat(state_str, tmp, sizeof(state_str));
    1425             :                 }
    1426             : 
    1427           8 :                 if (json) {
    1428           8 :                         char grp_str[PIM_ADDRSTRLEN];
    1429           8 :                         char src_str[PIM_ADDRSTRLEN];
    1430             : 
    1431           8 :                         snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
    1432             :                                    &up->sg.grp);
    1433           8 :                         snprintfrr(src_str, sizeof(src_str), "%pPAs",
    1434             :                                    &up->sg.src);
    1435             : 
    1436           8 :                         json_object_object_get_ex(json, grp_str, &json_group);
    1437             : 
    1438           8 :                         if (!json_group) {
    1439           5 :                                 json_group = json_object_new_object();
    1440           5 :                                 json_object_object_add(json, grp_str,
    1441             :                                                        json_group);
    1442             :                         }
    1443             : 
    1444           8 :                         json_row = json_object_new_object();
    1445           8 :                         json_object_pim_upstream_add(json_row, up);
    1446           8 :                         json_object_string_add(
    1447             :                                 json_row, "inboundInterface",
    1448           8 :                                 up->rpf.source_nexthop.interface
    1449             :                                 ? up->rpf.source_nexthop.interface->name
    1450             :                                 : "Unknown");
    1451             : 
    1452             :                         /*
    1453             :                          * The RPF address we use is slightly different
    1454             :                          * based upon what we are looking up.
    1455             :                          * If we have a S, list that unless
    1456             :                          * we are the FHR, else we just put
    1457             :                          * the RP as the rpfAddress
    1458             :                          */
    1459           8 :                         if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR ||
    1460           9 :                             pim_addr_is_any(up->sg.src)) {
    1461           7 :                                 struct pim_rpf *rpg;
    1462             : 
    1463           7 :                                 rpg = RP(pim, up->sg.grp);
    1464           7 :                                 json_object_string_addf(json_row, "rpfAddress",
    1465             :                                                         "%pPA", &rpg->rpf_addr);
    1466             :                         } else {
    1467           1 :                                 json_object_string_add(json_row, "rpfAddress",
    1468             :                                                        src_str);
    1469             :                         }
    1470             : 
    1471           8 :                         json_object_string_add(json_row, "source", src_str);
    1472           8 :                         json_object_string_add(json_row, "group", grp_str);
    1473           8 :                         json_object_string_add(json_row, "state", state_str);
    1474           8 :                         json_object_string_add(
    1475             :                                 json_row, "joinState",
    1476             :                                 pim_upstream_state2str(up->join_state));
    1477           8 :                         json_object_string_add(
    1478             :                                 json_row, "regState",
    1479             :                                 pim_reg_state2str(up->reg_state, state_str,
    1480             :                                                   sizeof(state_str)));
    1481           8 :                         json_object_string_add(json_row, "upTime", uptime);
    1482           8 :                         json_object_string_add(json_row, "joinTimer",
    1483             :                                                join_timer);
    1484           8 :                         json_object_string_add(json_row, "resetTimer",
    1485             :                                                rs_timer);
    1486           8 :                         json_object_string_add(json_row, "keepaliveTimer",
    1487             :                                                ka_timer);
    1488           8 :                         json_object_string_add(json_row, "msdpRegTimer",
    1489             :                                                msdp_reg_timer);
    1490           8 :                         json_object_int_add(json_row, "refCount",
    1491           8 :                                             up->ref_count);
    1492           8 :                         json_object_int_add(json_row, "sptBit", up->sptbit);
    1493           8 :                         json_object_object_add(json_group, src_str, json_row);
    1494             :                 } else {
    1495           0 :                         ttable_add_row(tt,
    1496             :                                 "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s|%d",
    1497           0 :                                 up->rpf.source_nexthop.interface
    1498             :                                 ? up->rpf.source_nexthop.interface->name
    1499             :                                 : "Unknown",
    1500             :                                 &up->sg.src, &up->sg.grp, state_str, uptime,
    1501             :                                 join_timer, rs_timer, ka_timer, up->ref_count);
    1502             :                 }
    1503             :         }
    1504             :         /* Dump the generated table. */
    1505           4 :         if (!json) {
    1506           0 :                 table = ttable_dump(tt, "\n");
    1507           0 :                 vty_out(vty, "%s\n", table);
    1508           0 :                 XFREE(MTYPE_TMP, table);
    1509           0 :                 ttable_del(tt);
    1510             :         }
    1511           4 : }
    1512             : 
    1513           0 : static void pim_show_join_desired_helper(struct pim_instance *pim,
    1514             :                                          struct vty *vty,
    1515             :                                          struct pim_upstream *up,
    1516             :                                          json_object *json, bool uj,
    1517             :                                          struct ttable *tt)
    1518             : {
    1519           0 :         json_object *json_group = NULL;
    1520           0 :         json_object *json_row = NULL;
    1521             : 
    1522           0 :         if (uj) {
    1523           0 :                 char grp_str[PIM_ADDRSTRLEN];
    1524           0 :                 char src_str[PIM_ADDRSTRLEN];
    1525             : 
    1526           0 :                 snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
    1527           0 :                 snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src);
    1528             : 
    1529           0 :                 json_object_object_get_ex(json, grp_str, &json_group);
    1530             : 
    1531           0 :                 if (!json_group) {
    1532           0 :                         json_group = json_object_new_object();
    1533           0 :                         json_object_object_add(json, grp_str, json_group);
    1534             :                 }
    1535             : 
    1536           0 :                 json_row = json_object_new_object();
    1537           0 :                 json_object_pim_upstream_add(json_row, up);
    1538           0 :                 json_object_string_add(json_row, "source", src_str);
    1539           0 :                 json_object_string_add(json_row, "group", grp_str);
    1540             : 
    1541           0 :                 if (pim_upstream_evaluate_join_desired(pim, up))
    1542           0 :                         json_object_boolean_true_add(json_row,
    1543             :                                                      "evaluateJoinDesired");
    1544             : 
    1545           0 :                 json_object_object_add(json_group, src_str, json_row);
    1546             : 
    1547             :         } else {
    1548           0 :                 ttable_add_row(tt, "%pPAs|%pPAs|%s", &up->sg.src, &up->sg.grp,
    1549           0 :                                pim_upstream_evaluate_join_desired(pim, up)
    1550             :                                        ? "yes"
    1551             :                                        : "no");
    1552             :         }
    1553           0 : }
    1554             : 
    1555           0 : void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj)
    1556             : {
    1557           0 :         struct pim_upstream *up;
    1558           0 :         struct ttable *tt = NULL;
    1559           0 :         char *table = NULL;
    1560             : 
    1561           0 :         json_object *json = NULL;
    1562             : 
    1563           0 :         if (uj)
    1564           0 :                 json = json_object_new_object();
    1565             :         else {
    1566             :                 /* Prepare table. */
    1567           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    1568           0 :                 ttable_add_row(tt, "Source|Group|EvalJD");
    1569           0 :                 tt->style.cell.rpad = 2;
    1570           0 :                 tt->style.corner = '+';
    1571           0 :                 ttable_restyle(tt);
    1572             :         }
    1573             : 
    1574           0 :         frr_each (rb_pim_upstream, &pim->upstream_head, up) {
    1575             :                 /* scan all interfaces */
    1576           0 :                 pim_show_join_desired_helper(pim, vty, up, json, uj, tt);
    1577             :         }
    1578             : 
    1579           0 :         if (uj)
    1580           0 :                 vty_json(vty, json);
    1581             :         else {
    1582             :                 /* Dump the generated table. */
    1583           0 :                 table = ttable_dump(tt, "\n");
    1584           0 :                 vty_out(vty, "%s\n", table);
    1585           0 :                 XFREE(MTYPE_TMP, table);
    1586           0 :                 ttable_del(tt);
    1587             :         }
    1588           0 : }
    1589             : 
    1590           0 : void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
    1591             : {
    1592           0 :         struct pim_upstream *up;
    1593           0 :         struct ttable *tt = NULL;
    1594           0 :         char *table = NULL;
    1595           0 :         json_object *json = NULL;
    1596           0 :         json_object *json_group = NULL;
    1597           0 :         json_object *json_row = NULL;
    1598             : 
    1599           0 :         if (uj)
    1600           0 :                 json = json_object_new_object();
    1601             :         else {
    1602             :                 /* Prepare table. */
    1603           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    1604           0 :                 ttable_add_row(tt,
    1605             :                                "Source|Group|RpfIface|RibNextHop|RpfAddress");
    1606           0 :                 tt->style.cell.rpad = 2;
    1607           0 :                 tt->style.corner = '+';
    1608           0 :                 ttable_restyle(tt);
    1609             :         }
    1610             : 
    1611           0 :         frr_each (rb_pim_upstream, &pim->upstream_head, up) {
    1612           0 :                 struct pim_rpf *rpf;
    1613           0 :                 const char *rpf_ifname;
    1614             : 
    1615           0 :                 rpf = &up->rpf;
    1616             : 
    1617           0 :                 rpf_ifname =
    1618           0 :                         rpf->source_nexthop.interface ? rpf->source_nexthop
    1619             :                                                                 .interface->name
    1620           0 :                                                       : "<ifname?>";
    1621             : 
    1622           0 :                 if (uj) {
    1623           0 :                         char grp_str[PIM_ADDRSTRLEN];
    1624           0 :                         char src_str[PIM_ADDRSTRLEN];
    1625             : 
    1626           0 :                         snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
    1627             :                                    &up->sg.grp);
    1628           0 :                         snprintfrr(src_str, sizeof(src_str), "%pPAs",
    1629             :                                    &up->sg.src);
    1630           0 :                         json_object_object_get_ex(json, grp_str, &json_group);
    1631             : 
    1632           0 :                         if (!json_group) {
    1633           0 :                                 json_group = json_object_new_object();
    1634           0 :                                 json_object_object_add(json, grp_str,
    1635             :                                                        json_group);
    1636             :                         }
    1637             : 
    1638           0 :                         json_row = json_object_new_object();
    1639           0 :                         json_object_pim_upstream_add(json_row, up);
    1640           0 :                         json_object_string_add(json_row, "source", src_str);
    1641           0 :                         json_object_string_add(json_row, "group", grp_str);
    1642           0 :                         json_object_string_add(json_row, "rpfInterface",
    1643             :                                                rpf_ifname);
    1644           0 :                         json_object_string_addf(
    1645             :                                 json_row, "ribNexthop", "%pPAs",
    1646             :                                 &rpf->source_nexthop.mrib_nexthop_addr);
    1647           0 :                         json_object_string_addf(json_row, "rpfAddress", "%pPA",
    1648             :                                                 &rpf->rpf_addr);
    1649           0 :                         json_object_object_add(json_group, src_str, json_row);
    1650             :                 } else {
    1651           0 :                         ttable_add_row(tt, "%pPAs|%pPAs|%s|%pPA|%pPA",
    1652             :                                        &up->sg.src, &up->sg.grp, rpf_ifname,
    1653             :                                        &rpf->source_nexthop.mrib_nexthop_addr,
    1654             :                                        &rpf->rpf_addr);
    1655             :                 }
    1656             :         }
    1657             : 
    1658           0 :         if (uj)
    1659           0 :                 vty_json(vty, json);
    1660             :         else {
    1661             :                 /* Dump the generated table. */
    1662           0 :                 table = ttable_dump(tt, "\n");
    1663           0 :                 vty_out(vty, "%s\n", table);
    1664           0 :                 XFREE(MTYPE_TMP, table);
    1665           0 :                 ttable_del(tt);
    1666             :         }
    1667           0 : }
    1668             : 
    1669          17 : static void pim_show_join_helper(struct pim_interface *pim_ifp,
    1670             :                                  struct pim_ifchannel *ch, json_object *json,
    1671             :                                  time_t now, struct ttable *tt)
    1672             : {
    1673          17 :         json_object *json_iface = NULL;
    1674          17 :         json_object *json_row = NULL;
    1675          17 :         json_object *json_grp = NULL;
    1676          17 :         pim_addr ifaddr;
    1677          17 :         char uptime[10];
    1678          17 :         char expire[10];
    1679          17 :         char prune[10];
    1680             : 
    1681          17 :         ifaddr = pim_ifp->primary_address;
    1682             : 
    1683          17 :         pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
    1684          17 :         pim_time_timer_to_mmss(expire, sizeof(expire),
    1685             :                                ch->t_ifjoin_expiry_timer);
    1686          17 :         pim_time_timer_to_mmss(prune, sizeof(prune),
    1687             :                                ch->t_ifjoin_prune_pending_timer);
    1688             : 
    1689          17 :         if (json) {
    1690          17 :                 char ch_grp_str[PIM_ADDRSTRLEN];
    1691             : 
    1692          17 :                 json_object_object_get_ex(json, ch->interface->name,
    1693             :                                           &json_iface);
    1694             : 
    1695          17 :                 if (!json_iface) {
    1696          17 :                         json_iface = json_object_new_object();
    1697          17 :                         json_object_pim_ifp_add(json_iface, ch->interface);
    1698          17 :                         json_object_object_add(json, ch->interface->name,
    1699             :                                                json_iface);
    1700             :                 }
    1701             : 
    1702          17 :                 json_row = json_object_new_object();
    1703          17 :                 json_object_string_addf(json_row, "source", "%pPAs",
    1704             :                                         &ch->sg.src);
    1705          17 :                 json_object_string_addf(json_row, "group", "%pPAs",
    1706             :                                         &ch->sg.grp);
    1707          17 :                 json_object_string_add(json_row, "upTime", uptime);
    1708          17 :                 json_object_string_add(json_row, "expire", expire);
    1709          17 :                 json_object_string_add(json_row, "prune", prune);
    1710          17 :                 json_object_string_add(
    1711             :                         json_row, "channelJoinName",
    1712          17 :                         pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
    1713          17 :                 if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
    1714           0 :                         json_object_int_add(json_row, "sgRpt", 1);
    1715          17 :                 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
    1716          15 :                         json_object_int_add(json_row, "protocolPim", 1);
    1717          17 :                 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
    1718           1 :                         json_object_int_add(json_row, "protocolIgmp", 1);
    1719          17 :                 snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
    1720             :                            &ch->sg.grp);
    1721          17 :                 json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
    1722          17 :                 if (!json_grp) {
    1723          17 :                         json_grp = json_object_new_object();
    1724          17 :                         json_object_object_addf(json_grp, json_row, "%pPAs",
    1725             :                                                 &ch->sg.src);
    1726          17 :                         json_object_object_addf(json_iface, json_grp, "%pPAs",
    1727             :                                                 &ch->sg.grp);
    1728             :                 } else
    1729           0 :                         json_object_object_addf(json_grp, json_row, "%pPAs",
    1730             :                                                 &ch->sg.src);
    1731             :         } else {
    1732           0 :                 ttable_add_row(
    1733             :                         tt, "%s|%pPAs|%pPAs|%pPAs|%s|%s|%s|%s",
    1734           0 :                         ch->interface->name, &ifaddr, &ch->sg.src, &ch->sg.grp,
    1735           0 :                         pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
    1736             :                         uptime, expire, prune);
    1737             :         }
    1738          17 : }
    1739             : 
    1740          18 : int pim_show_join_cmd_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
    1741             :                              pim_addr g, const char *json)
    1742             : {
    1743          18 :         pim_sgaddr sg = {};
    1744          18 :         struct vrf *v;
    1745          18 :         struct pim_instance *pim;
    1746          18 :         json_object *json_parent = NULL;
    1747             : 
    1748          18 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    1749             : 
    1750          18 :         if (!v) {
    1751           0 :                 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
    1752           0 :                 return CMD_WARNING;
    1753             :         }
    1754          18 :         pim = v->info;
    1755             : 
    1756          18 :         if (!pim) {
    1757           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    1758           0 :                 return CMD_WARNING;
    1759             :         }
    1760             : 
    1761          18 :         if (!pim_addr_is_any(s_or_g)) {
    1762           0 :                 if (!pim_addr_is_any(g)) {
    1763           0 :                         sg.src = s_or_g;
    1764           0 :                         sg.grp = g;
    1765             :                 } else
    1766           0 :                         sg.grp = s_or_g;
    1767             :         }
    1768             : 
    1769          18 :         if (json)
    1770          18 :                 json_parent = json_object_new_object();
    1771             : 
    1772          18 :         pim_show_join(pim, vty, &sg, json_parent);
    1773             : 
    1774          18 :         if (json)
    1775          18 :                 vty_json(vty, json_parent);
    1776             : 
    1777             :         return CMD_SUCCESS;
    1778             : }
    1779             : 
    1780           0 : int pim_show_join_vrf_all_cmd_helper(struct vty *vty, const char *json)
    1781             : {
    1782           0 :         pim_sgaddr sg = {0};
    1783           0 :         struct vrf *vrf_struct;
    1784           0 :         json_object *json_parent = NULL;
    1785           0 :         json_object *json_vrf = NULL;
    1786             : 
    1787           0 :         if (json)
    1788           0 :                 json_parent = json_object_new_object();
    1789             : 
    1790           0 :         RB_FOREACH (vrf_struct, vrf_name_head, &vrfs_by_name) {
    1791           0 :                 if (!json_parent)
    1792           0 :                         vty_out(vty, "VRF: %s\n", vrf_struct->name);
    1793             :                 else
    1794           0 :                         json_vrf = json_object_new_object();
    1795           0 :                 pim_show_join(vrf_struct->info, vty, &sg, json_vrf);
    1796             : 
    1797           0 :                 if (json)
    1798           0 :                         json_object_object_add(json_parent, vrf_struct->name,
    1799             :                                                json_vrf);
    1800             :         }
    1801           0 :         if (json)
    1802           0 :                 vty_json(vty, json_parent);
    1803             : 
    1804           0 :         return CMD_WARNING;
    1805             : }
    1806             : 
    1807          18 : void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
    1808             :                    json_object *json)
    1809             : {
    1810          18 :         struct pim_interface *pim_ifp;
    1811          18 :         struct pim_ifchannel *ch;
    1812          18 :         struct interface *ifp;
    1813          18 :         time_t now;
    1814          18 :         struct ttable *tt = NULL;
    1815          18 :         char *table = NULL;
    1816             : 
    1817          18 :         now = pim_time_monotonic_sec();
    1818             : 
    1819          18 :         if (!json) {
    1820             :                 /* Prepare table. */
    1821           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    1822           0 :                 ttable_add_row(
    1823             :                         tt,
    1824             :                         "Interface|Address|Source|Group|State|Uptime|Expire|Prune");
    1825           0 :                 tt->style.cell.rpad = 2;
    1826           0 :                 tt->style.corner = '+';
    1827           0 :                 ttable_restyle(tt);
    1828             :         }
    1829             : 
    1830         108 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    1831          72 :                 pim_ifp = ifp->info;
    1832          72 :                 if (!pim_ifp)
    1833          18 :                         continue;
    1834             : 
    1835         125 :                 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
    1836          17 :                         if (!pim_sgaddr_match(ch->sg, *sg))
    1837           0 :                                 continue;
    1838             : 
    1839          17 :                         pim_show_join_helper(pim_ifp, ch, json, now, tt);
    1840             :                 } /* scan interface channels */
    1841             :         }
    1842             :         /* Dump the generated table. */
    1843          18 :         if (!json) {
    1844           0 :                 table = ttable_dump(tt, "\n");
    1845           0 :                 vty_out(vty, "%s\n", table);
    1846           0 :                 XFREE(MTYPE_TMP, table);
    1847           0 :                 ttable_del(tt);
    1848             :         }
    1849          18 : }
    1850             : 
    1851           0 : static void pim_show_jp_agg_helper(struct interface *ifp,
    1852             :                                    struct pim_neighbor *neigh,
    1853             :                                    struct pim_upstream *up, int is_join,
    1854             :                                    struct ttable *tt)
    1855             : {
    1856           0 :         ttable_add_row(tt, "%s|%pPAs|%pPAs|%pPAs|%s", ifp->name,
    1857             :                        &neigh->source_addr, &up->sg.src, &up->sg.grp,
    1858             :                        is_join ? "J" : "P");
    1859           0 : }
    1860             : 
    1861           0 : int pim_show_jp_agg_list_cmd_helper(const char *vrf, struct vty *vty)
    1862             : {
    1863           0 :         struct vrf *v;
    1864           0 :         struct pim_instance *pim;
    1865             : 
    1866           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    1867             : 
    1868           0 :         if (!v) {
    1869           0 :                 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
    1870           0 :                 return CMD_WARNING;
    1871             :         }
    1872           0 :         pim = v->info;
    1873             : 
    1874           0 :         if (!pim) {
    1875           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    1876           0 :                 return CMD_WARNING;
    1877             :         }
    1878             : 
    1879           0 :         pim_show_jp_agg_list(pim, vty);
    1880             : 
    1881           0 :         return CMD_SUCCESS;
    1882             : }
    1883             : 
    1884           0 : void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
    1885             : {
    1886           0 :         struct interface *ifp;
    1887           0 :         struct pim_interface *pim_ifp;
    1888           0 :         struct listnode *n_node;
    1889           0 :         struct pim_neighbor *neigh;
    1890           0 :         struct listnode *jag_node;
    1891           0 :         struct pim_jp_agg_group *jag;
    1892           0 :         struct listnode *js_node;
    1893           0 :         struct pim_jp_sources *js;
    1894           0 :         struct ttable *tt;
    1895           0 :         char *table;
    1896             : 
    1897             :         /* Prepare table. */
    1898           0 :         tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    1899           0 :         ttable_add_row(tt, "Interface|RPF Nbr|Source|Group|State");
    1900           0 :         tt->style.cell.rpad = 2;
    1901           0 :         tt->style.corner = '+';
    1902           0 :         ttable_restyle(tt);
    1903             : 
    1904           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    1905           0 :                 pim_ifp = ifp->info;
    1906           0 :                 if (!pim_ifp)
    1907           0 :                         continue;
    1908             : 
    1909           0 :                 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, n_node,
    1910             :                                           neigh)) {
    1911           0 :                         for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
    1912             :                                                   jag_node, jag)) {
    1913           0 :                                 for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
    1914             :                                                           js)) {
    1915           0 :                                         pim_show_jp_agg_helper(ifp, neigh,
    1916             :                                                                js->up,
    1917             :                                                                js->is_join, tt);
    1918             :                                 }
    1919             :                         }
    1920             :                 }
    1921             :         }
    1922             : 
    1923             :         /* Dump the generated table. */
    1924           0 :         table = ttable_dump(tt, "\n");
    1925           0 :         vty_out(vty, "%s\n", table);
    1926           0 :         XFREE(MTYPE_TMP, table);
    1927           0 :         ttable_del(tt);
    1928           0 : }
    1929             : 
    1930           0 : int pim_show_membership_cmd_helper(const char *vrf, struct vty *vty, bool uj)
    1931             : {
    1932           0 :         struct vrf *v;
    1933             : 
    1934           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    1935             : 
    1936           0 :         if (!v)
    1937             :                 return CMD_WARNING;
    1938             : 
    1939           0 :         pim_show_membership(v->info, vty, uj);
    1940             : 
    1941           0 :         return CMD_SUCCESS;
    1942             : }
    1943             : 
    1944           0 : static void pim_show_membership_helper(struct vty *vty,
    1945             :                                        struct pim_interface *pim_ifp,
    1946             :                                        struct pim_ifchannel *ch,
    1947             :                                        struct json_object *json)
    1948             : {
    1949           0 :         json_object *json_iface = NULL;
    1950           0 :         json_object *json_row = NULL;
    1951             : 
    1952           0 :         json_object_object_get_ex(json, ch->interface->name, &json_iface);
    1953           0 :         if (!json_iface) {
    1954           0 :                 json_iface = json_object_new_object();
    1955           0 :                 json_object_pim_ifp_add(json_iface, ch->interface);
    1956           0 :                 json_object_object_add(json, ch->interface->name, json_iface);
    1957             :         }
    1958             : 
    1959           0 :         json_row = json_object_new_object();
    1960           0 :         json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
    1961           0 :         json_object_string_addf(json_row, "group", "%pPAs", &ch->sg.grp);
    1962           0 :         json_object_string_add(json_row, "localMembership",
    1963           0 :                                ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
    1964             :                                        ? "NOINFO"
    1965             :                                        : "INCLUDE");
    1966           0 :         json_object_object_addf(json_iface, json_row, "%pPAs", &ch->sg.grp);
    1967           0 : }
    1968             : 
    1969           0 : void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
    1970             : {
    1971           0 :         struct pim_interface *pim_ifp;
    1972           0 :         struct pim_ifchannel *ch;
    1973           0 :         struct interface *ifp;
    1974           0 :         enum json_type type;
    1975           0 :         json_object *json = NULL;
    1976           0 :         json_object *json_tmp = NULL;
    1977           0 :         struct ttable *tt = NULL;
    1978           0 :         char *table = NULL;
    1979             : 
    1980           0 :         json = json_object_new_object();
    1981             : 
    1982           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    1983           0 :                 pim_ifp = ifp->info;
    1984           0 :                 if (!pim_ifp)
    1985           0 :                         continue;
    1986             : 
    1987           0 :                 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
    1988           0 :                         pim_show_membership_helper(vty, pim_ifp, ch, json);
    1989             :                 } /* scan interface channels */
    1990             :         }
    1991             : 
    1992           0 :         if (uj) {
    1993           0 :                 vty_json(vty, json);
    1994             :         } else {
    1995             :                 /* Prepare table. */
    1996           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    1997           0 :                 ttable_add_row(tt, "Interface|Address|Source|Group|Membership");
    1998           0 :                 tt->style.cell.rpad = 2;
    1999           0 :                 tt->style.corner = '+';
    2000           0 :                 ttable_restyle(tt);
    2001             : 
    2002             :                 /*
    2003             :                  * Example of the json data we are traversing
    2004             :                  *
    2005             :                  * {
    2006             :                  *   "swp3":{
    2007             :                  *     "name":"swp3",
    2008             :                  *     "state":"up",
    2009             :                  *     "address":"10.1.20.1",
    2010             :                  *     "index":5,
    2011             :                  *     "flagMulticast":true,
    2012             :                  *     "flagBroadcast":true,
    2013             :                  *     "lanDelayEnabled":true,
    2014             :                  *     "226.10.10.10":{
    2015             :                  *       "source":"*",
    2016             :                  *       "group":"226.10.10.10",
    2017             :                  *       "localMembership":"INCLUDE"
    2018             :                  *     }
    2019             :                  *   }
    2020             :                  * }
    2021             :                  */
    2022             : 
    2023             :                 /* foreach interface */
    2024           0 :                 json_object_object_foreach(json, key, val)
    2025             :                 {
    2026             : 
    2027             :                         /* Find all of the keys where the val is an object. In
    2028             :                          * the example
    2029             :                          * above the only one is 226.10.10.10
    2030             :                          */
    2031           0 :                         json_object_object_foreach(val, if_field_key,
    2032             :                                                    if_field_val)
    2033             :                         {
    2034           0 :                                 type = json_object_get_type(if_field_val);
    2035             : 
    2036           0 :                                 if (type == json_type_object) {
    2037           0 :                                         const char *address, *source,
    2038             :                                                 *localMembership;
    2039             : 
    2040           0 :                                         json_object_object_get_ex(
    2041             :                                                 val, "address", &json_tmp);
    2042           0 :                                         address = json_object_get_string(
    2043             :                                                 json_tmp);
    2044             : 
    2045           0 :                                         json_object_object_get_ex(if_field_val,
    2046             :                                                                   "source",
    2047             :                                                                   &json_tmp);
    2048           0 :                                         source = json_object_get_string(
    2049             :                                                 json_tmp);
    2050             : 
    2051           0 :                                         json_object_object_get_ex(
    2052             :                                                 if_field_val, "localMembership",
    2053             :                                                 &json_tmp);
    2054           0 :                                         localMembership =
    2055           0 :                                                 json_object_get_string(
    2056             :                                                         json_tmp);
    2057             : 
    2058           0 :                                         ttable_add_row(tt, "%s|%s|%s|%s|%s",
    2059             :                                                        key, address, source,
    2060             :                                                        if_field_key,
    2061             :                                                        localMembership);
    2062             :                                 }
    2063             :                         }
    2064             :                 }
    2065           0 :                 json_object_free(json);
    2066             :                 /* Dump the generated table. */
    2067           0 :                 table = ttable_dump(tt, "\n");
    2068           0 :                 vty_out(vty, "%s\n", table);
    2069           0 :                 XFREE(MTYPE_TMP, table);
    2070           0 :                 ttable_del(tt);
    2071             :         }
    2072           0 : }
    2073             : 
    2074           0 : static void pim_show_channel_helper(struct pim_instance *pim,
    2075             :                                     struct pim_interface *pim_ifp,
    2076             :                                     struct pim_ifchannel *ch, json_object *json,
    2077             :                                     bool uj, struct ttable *tt)
    2078             : {
    2079           0 :         struct pim_upstream *up = ch->upstream;
    2080           0 :         json_object *json_group = NULL;
    2081           0 :         json_object *json_row = NULL;
    2082             : 
    2083           0 :         if (uj) {
    2084           0 :                 char grp_str[PIM_ADDRSTRLEN];
    2085             : 
    2086           0 :                 snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
    2087           0 :                 json_object_object_get_ex(json, grp_str, &json_group);
    2088             : 
    2089           0 :                 if (!json_group) {
    2090           0 :                         json_group = json_object_new_object();
    2091           0 :                         json_object_object_add(json, grp_str, json_group);
    2092             :                 }
    2093             : 
    2094           0 :                 json_row = json_object_new_object();
    2095           0 :                 json_object_pim_upstream_add(json_row, up);
    2096           0 :                 json_object_string_add(json_row, "interface",
    2097           0 :                                        ch->interface->name);
    2098           0 :                 json_object_string_addf(json_row, "source", "%pPAs",
    2099             :                                         &up->sg.src);
    2100           0 :                 json_object_string_addf(json_row, "group", "%pPAs",
    2101             :                                         &up->sg.grp);
    2102             : 
    2103           0 :                 if (pim_macro_ch_lost_assert(ch))
    2104           0 :                         json_object_boolean_true_add(json_row, "lostAssert");
    2105             : 
    2106           0 :                 if (pim_macro_chisin_joins(ch))
    2107           0 :                         json_object_boolean_true_add(json_row, "joins");
    2108             : 
    2109           0 :                 if (pim_macro_chisin_pim_include(ch))
    2110           0 :                         json_object_boolean_true_add(json_row, "pimInclude");
    2111             : 
    2112           0 :                 if (pim_upstream_evaluate_join_desired(pim, up))
    2113           0 :                         json_object_boolean_true_add(json_row,
    2114             :                                                      "evaluateJoinDesired");
    2115             : 
    2116           0 :                 json_object_object_addf(json_group, json_row, "%pPAs",
    2117             :                                         &up->sg.src);
    2118             : 
    2119             :         } else {
    2120           0 :                 ttable_add_row(tt, "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s",
    2121           0 :                                ch->interface->name, &up->sg.src, &up->sg.grp,
    2122           0 :                                pim_macro_ch_lost_assert(ch) ? "yes" : "no",
    2123           0 :                                pim_macro_chisin_joins(ch) ? "yes" : "no",
    2124           0 :                                pim_macro_chisin_pim_include(ch) ? "yes" : "no",
    2125           0 :                                PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
    2126             :                                        ? "yes"
    2127             :                                        : "no",
    2128           0 :                                pim_upstream_evaluate_join_desired(pim, up)
    2129             :                                        ? "yes"
    2130             :                                        : "no");
    2131             :         }
    2132           0 : }
    2133             : 
    2134           0 : void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
    2135             : {
    2136           0 :         struct pim_interface *pim_ifp;
    2137           0 :         struct pim_ifchannel *ch;
    2138           0 :         struct interface *ifp;
    2139           0 :         struct ttable *tt = NULL;
    2140           0 :         json_object *json = NULL;
    2141           0 :         char *table = NULL;
    2142             : 
    2143           0 :         if (uj)
    2144           0 :                 json = json_object_new_object();
    2145             :         else {
    2146             :                 /* Prepare table. */
    2147           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    2148           0 :                 ttable_add_row(
    2149             :                         tt,
    2150             :                         "Interface|Source|Group|LostAssert|Joins|PimInclude|JoinDesired|EvalJD");
    2151           0 :                 tt->style.cell.rpad = 2;
    2152           0 :                 tt->style.corner = '+';
    2153           0 :                 ttable_restyle(tt);
    2154             :         }
    2155             : 
    2156             :         /* scan per-interface (S,G) state */
    2157           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    2158           0 :                 pim_ifp = ifp->info;
    2159           0 :                 if (!pim_ifp)
    2160           0 :                         continue;
    2161             : 
    2162           0 :                 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
    2163             :                         /* scan all interfaces */
    2164           0 :                         pim_show_channel_helper(pim, pim_ifp, ch, json, uj, tt);
    2165             :                 }
    2166             :         }
    2167             : 
    2168           0 :         if (uj)
    2169           0 :                 vty_json(vty, json);
    2170             :         else {
    2171             :                 /* Dump the generated table. */
    2172           0 :                 table = ttable_dump(tt, "\n");
    2173           0 :                 vty_out(vty, "%s\n", table);
    2174           0 :                 XFREE(MTYPE_TMP, table);
    2175           0 :                 ttable_del(tt);
    2176             :         }
    2177           0 : }
    2178             : 
    2179           0 : int pim_show_channel_cmd_helper(const char *vrf, struct vty *vty, bool uj)
    2180             : {
    2181           0 :         struct vrf *v;
    2182             : 
    2183           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    2184             : 
    2185           0 :         if (!v)
    2186             :                 return CMD_WARNING;
    2187             : 
    2188           0 :         pim_show_channel(v->info, vty, uj);
    2189             : 
    2190           0 :         return CMD_SUCCESS;
    2191             : }
    2192             : 
    2193           0 : int pim_show_interface_cmd_helper(const char *vrf, struct vty *vty, bool uj,
    2194             :                                   bool mlag, const char *interface)
    2195             : {
    2196           0 :         struct vrf *v;
    2197           0 :         json_object *json_parent = NULL;
    2198             : 
    2199           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    2200             : 
    2201           0 :         if (!v)
    2202             :                 return CMD_WARNING;
    2203             : 
    2204           0 :         if (uj)
    2205           0 :                 json_parent = json_object_new_object();
    2206             : 
    2207           0 :         if (interface)
    2208           0 :                 pim_show_interfaces_single(v->info, vty, interface, mlag,
    2209             :                                            json_parent);
    2210             :         else
    2211           0 :                 pim_show_interfaces(v->info, vty, mlag, json_parent);
    2212             : 
    2213           0 :         if (uj)
    2214           0 :                 vty_json(vty, json_parent);
    2215             : 
    2216             :         return CMD_SUCCESS;
    2217             : }
    2218             : 
    2219           0 : int pim_show_interface_vrf_all_cmd_helper(struct vty *vty, bool uj, bool mlag,
    2220             :                                           const char *interface)
    2221             : {
    2222           0 :         struct vrf *v;
    2223           0 :         json_object *json_parent = NULL;
    2224           0 :         json_object *json_vrf = NULL;
    2225             : 
    2226           0 :         if (uj)
    2227           0 :                 json_parent = json_object_new_object();
    2228             : 
    2229           0 :         RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
    2230           0 :                 if (!uj)
    2231           0 :                         vty_out(vty, "VRF: %s\n", v->name);
    2232             :                 else
    2233           0 :                         json_vrf = json_object_new_object();
    2234             : 
    2235           0 :                 if (interface)
    2236           0 :                         pim_show_interfaces_single(v->info, vty, interface,
    2237             :                                                    mlag, json_vrf);
    2238             :                 else
    2239           0 :                         pim_show_interfaces(v->info, vty, mlag, json_vrf);
    2240             : 
    2241           0 :                 if (uj)
    2242           0 :                         json_object_object_add(json_parent, v->name, json_vrf);
    2243             :         }
    2244           0 :         if (uj)
    2245           0 :                 vty_json(vty, json_parent);
    2246             : 
    2247           0 :         return CMD_SUCCESS;
    2248             : }
    2249             : 
    2250           0 : void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
    2251             :                          json_object *json)
    2252             : {
    2253           0 :         struct interface *ifp;
    2254           0 :         struct pim_interface *pim_ifp;
    2255           0 :         struct pim_upstream *up;
    2256           0 :         int fhr = 0;
    2257           0 :         int pim_nbrs = 0;
    2258           0 :         int pim_ifchannels = 0;
    2259           0 :         bool uj = true;
    2260           0 :         struct ttable *tt = NULL;
    2261           0 :         char *table = NULL;
    2262           0 :         json_object *json_row = NULL;
    2263           0 :         json_object *json_tmp;
    2264             : 
    2265           0 :         if (!json) {
    2266           0 :                 uj = false;
    2267           0 :                 json = json_object_new_object();
    2268             :         }
    2269             : 
    2270           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    2271           0 :                 pim_ifp = ifp->info;
    2272             : 
    2273           0 :                 if (!pim_ifp)
    2274           0 :                         continue;
    2275             : 
    2276           0 :                 if (mlag == true && pim_ifp->activeactive == false)
    2277           0 :                         continue;
    2278             : 
    2279           0 :                 pim_nbrs = pim_ifp->pim_neighbor_list->count;
    2280           0 :                 pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
    2281           0 :                 fhr = 0;
    2282             : 
    2283           0 :                 frr_each (rb_pim_upstream, &pim->upstream_head, up)
    2284           0 :                         if (ifp == up->rpf.source_nexthop.interface)
    2285           0 :                                 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
    2286           0 :                                         fhr++;
    2287             : 
    2288           0 :                 json_row = json_object_new_object();
    2289           0 :                 json_object_pim_ifp_add(json_row, ifp);
    2290           0 :                 json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
    2291           0 :                 json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
    2292           0 :                 json_object_int_add(json_row, "firstHopRouterCount", fhr);
    2293           0 :                 json_object_string_addf(json_row, "pimDesignatedRouter",
    2294             :                                         "%pPAs", &pim_ifp->pim_dr_addr);
    2295             : 
    2296           0 :                 if (!pim_addr_cmp(pim_ifp->pim_dr_addr,
    2297             :                                   pim_ifp->primary_address))
    2298           0 :                         json_object_boolean_true_add(
    2299             :                                 json_row, "pimDesignatedRouterLocal");
    2300             : 
    2301           0 :                 json_object_object_add(json, ifp->name, json_row);
    2302             :         }
    2303             : 
    2304           0 :         if (!uj) {
    2305             : 
    2306             :                 /* Prepare table. */
    2307           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    2308           0 :                 ttable_add_row(
    2309             :                         tt,
    2310             :                         "Interface|State|Address|PIM Nbrs|PIM DR|FHR|IfChannels");
    2311           0 :                 tt->style.cell.rpad = 2;
    2312           0 :                 tt->style.corner = '+';
    2313           0 :                 ttable_restyle(tt);
    2314             : 
    2315           0 :                 json_object_object_foreach(json, key, val)
    2316             :                 {
    2317           0 :                         const char *state, *address, *pimdr;
    2318           0 :                         int neighbors, firsthpr, pimifchnl;
    2319             : 
    2320           0 :                         json_object_object_get_ex(val, "state", &json_tmp);
    2321           0 :                         state = json_object_get_string(json_tmp);
    2322             : 
    2323           0 :                         json_object_object_get_ex(val, "address", &json_tmp);
    2324           0 :                         address = json_object_get_string(json_tmp);
    2325             : 
    2326           0 :                         json_object_object_get_ex(val, "pimNeighbors",
    2327             :                                                   &json_tmp);
    2328           0 :                         neighbors = json_object_get_int(json_tmp);
    2329             : 
    2330           0 :                         if (json_object_object_get_ex(
    2331             :                                     val, "pimDesignatedRouterLocal",
    2332             :                                     &json_tmp)) {
    2333             :                                 pimdr = "local";
    2334             :                         } else {
    2335           0 :                                 json_object_object_get_ex(
    2336             :                                         val, "pimDesignatedRouter", &json_tmp);
    2337           0 :                                 pimdr = json_object_get_string(json_tmp);
    2338             :                         }
    2339             : 
    2340           0 :                         json_object_object_get_ex(val, "firstHopRouter",
    2341             :                                                   &json_tmp);
    2342           0 :                         firsthpr = json_object_get_int(json_tmp);
    2343             : 
    2344           0 :                         json_object_object_get_ex(val, "pimIfChannels",
    2345             :                                                   &json_tmp);
    2346           0 :                         pimifchnl = json_object_get_int(json_tmp);
    2347             : 
    2348           0 :                         ttable_add_row(tt, "%s|%s|%s|%d|%s|%d|%d", key, state,
    2349             :                                        address, neighbors, pimdr, firsthpr,
    2350             :                                        pimifchnl);
    2351             :                 }
    2352           0 :                 json_object_free(json);
    2353             : 
    2354             :                 /* Dump the generated table. */
    2355           0 :                 table = ttable_dump(tt, "\n");
    2356           0 :                 vty_out(vty, "%s\n", table);
    2357           0 :                 XFREE(MTYPE_TMP, table);
    2358             : 
    2359           0 :                 ttable_del(tt);
    2360             :         }
    2361           0 : }
    2362             : 
    2363           0 : void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty,
    2364             :                                 const char *ifname, bool mlag,
    2365             :                                 json_object *json)
    2366             : {
    2367           0 :         pim_addr ifaddr;
    2368           0 :         struct interface *ifp;
    2369           0 :         struct listnode *neighnode;
    2370           0 :         struct pim_interface *pim_ifp;
    2371           0 :         struct pim_neighbor *neigh;
    2372           0 :         struct pim_upstream *up;
    2373           0 :         time_t now;
    2374           0 :         char dr_str[PIM_ADDRSTRLEN];
    2375           0 :         char dr_uptime[10];
    2376           0 :         char expire[10];
    2377           0 :         char grp_str[PIM_ADDRSTRLEN];
    2378           0 :         char hello_period[10];
    2379           0 :         char hello_timer[10];
    2380           0 :         char neigh_src_str[PIM_ADDRSTRLEN];
    2381           0 :         char src_str[PIM_ADDRSTRLEN];
    2382           0 :         char stat_uptime[10];
    2383           0 :         char uptime[10];
    2384           0 :         int found_ifname = 0;
    2385           0 :         int print_header;
    2386           0 :         json_object *json_row = NULL;
    2387           0 :         json_object *json_pim_neighbor = NULL;
    2388           0 :         json_object *json_pim_neighbors = NULL;
    2389           0 :         json_object *json_group = NULL;
    2390           0 :         json_object *json_group_source = NULL;
    2391           0 :         json_object *json_fhr_sources = NULL;
    2392           0 :         struct pim_secondary_addr *sec_addr;
    2393           0 :         struct listnode *sec_node;
    2394             : 
    2395           0 :         now = pim_time_monotonic_sec();
    2396             : 
    2397           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    2398           0 :                 pim_ifp = ifp->info;
    2399             : 
    2400           0 :                 if (!pim_ifp)
    2401           0 :                         continue;
    2402             : 
    2403           0 :                 if (mlag == true && pim_ifp->activeactive == false)
    2404           0 :                         continue;
    2405             : 
    2406           0 :                 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
    2407           0 :                         continue;
    2408             : 
    2409           0 :                 found_ifname = 1;
    2410           0 :                 ifaddr = pim_ifp->primary_address;
    2411           0 :                 snprintfrr(dr_str, sizeof(dr_str), "%pPAs",
    2412             :                            &pim_ifp->pim_dr_addr);
    2413           0 :                 pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
    2414             :                                       pim_ifp->pim_dr_election_last);
    2415           0 :                 pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
    2416             :                                          pim_ifp->t_pim_hello_timer);
    2417           0 :                 pim_time_mmss(hello_period, sizeof(hello_period),
    2418           0 :                               pim_ifp->pim_hello_period);
    2419           0 :                 pim_time_uptime(stat_uptime, sizeof(stat_uptime),
    2420           0 :                                 now - pim_ifp->pim_ifstat_start);
    2421             : 
    2422           0 :                 if (json) {
    2423           0 :                         json_row = json_object_new_object();
    2424           0 :                         json_object_pim_ifp_add(json_row, ifp);
    2425             : 
    2426           0 :                         if (!pim_addr_is_any(pim_ifp->update_source)) {
    2427           0 :                                 json_object_string_addf(
    2428             :                                         json_row, "useSource", "%pPAs",
    2429             :                                         &pim_ifp->update_source);
    2430             :                         }
    2431           0 :                         if (pim_ifp->sec_addr_list) {
    2432           0 :                                 json_object *sec_list = NULL;
    2433             : 
    2434           0 :                                 sec_list = json_object_new_array();
    2435           0 :                                 for (ALL_LIST_ELEMENTS_RO(
    2436             :                                              pim_ifp->sec_addr_list, sec_node,
    2437             :                                              sec_addr)) {
    2438           0 :                                         json_object_array_add(
    2439             :                                                 sec_list,
    2440             :                                                 json_object_new_stringf(
    2441             :                                                         "%pFXh",
    2442             :                                                         &sec_addr->addr));
    2443             :                                 }
    2444           0 :                                 json_object_object_add(json_row,
    2445             :                                                        "secondaryAddressList",
    2446             :                                                        sec_list);
    2447             :                         }
    2448             : 
    2449           0 :                         if (pim_ifp->pim_passive_enable)
    2450           0 :                                 json_object_boolean_true_add(json_row,
    2451             :                                                              "passive");
    2452             : 
    2453             :                         /* PIM neighbors */
    2454           0 :                         if (pim_ifp->pim_neighbor_list->count) {
    2455           0 :                                 json_pim_neighbors = json_object_new_object();
    2456             : 
    2457           0 :                                 for (ALL_LIST_ELEMENTS_RO(
    2458             :                                              pim_ifp->pim_neighbor_list,
    2459             :                                              neighnode, neigh)) {
    2460           0 :                                         json_pim_neighbor =
    2461           0 :                                                 json_object_new_object();
    2462           0 :                                         snprintfrr(neigh_src_str,
    2463             :                                                    sizeof(neigh_src_str),
    2464             :                                                    "%pPAs",
    2465             :                                                    &neigh->source_addr);
    2466           0 :                                         pim_time_uptime(uptime, sizeof(uptime),
    2467           0 :                                                         now - neigh->creation);
    2468           0 :                                         pim_time_timer_to_hhmmss(
    2469             :                                                 expire, sizeof(expire),
    2470             :                                                 neigh->t_expire_timer);
    2471             : 
    2472           0 :                                         json_object_string_add(
    2473             :                                                 json_pim_neighbor, "address",
    2474             :                                                 neigh_src_str);
    2475           0 :                                         json_object_string_add(
    2476             :                                                 json_pim_neighbor, "upTime",
    2477             :                                                 uptime);
    2478           0 :                                         json_object_string_add(
    2479             :                                                 json_pim_neighbor, "holdtime",
    2480             :                                                 expire);
    2481             : 
    2482           0 :                                         json_object_object_add(
    2483             :                                                 json_pim_neighbors,
    2484             :                                                 neigh_src_str,
    2485             :                                                 json_pim_neighbor);
    2486             :                                 }
    2487             : 
    2488           0 :                                 json_object_object_add(json_row, "neighbors",
    2489             :                                                        json_pim_neighbors);
    2490             :                         }
    2491             : 
    2492           0 :                         json_object_string_add(json_row, "drAddress", dr_str);
    2493           0 :                         json_object_int_add(json_row, "drPriority",
    2494           0 :                                             pim_ifp->pim_dr_priority);
    2495           0 :                         json_object_string_add(json_row, "drUptime", dr_uptime);
    2496           0 :                         json_object_int_add(json_row, "drElections",
    2497           0 :                                             pim_ifp->pim_dr_election_count);
    2498           0 :                         json_object_int_add(json_row, "drChanges",
    2499           0 :                                             pim_ifp->pim_dr_election_changes);
    2500             : 
    2501             :                         /* FHR */
    2502           0 :                         frr_each (rb_pim_upstream, &pim->upstream_head, up) {
    2503           0 :                                 if (ifp != up->rpf.source_nexthop.interface)
    2504           0 :                                         continue;
    2505             : 
    2506           0 :                                 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
    2507           0 :                                         continue;
    2508             : 
    2509           0 :                                 if (!json_fhr_sources)
    2510           0 :                                         json_fhr_sources =
    2511           0 :                                                 json_object_new_object();
    2512             : 
    2513           0 :                                 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
    2514             :                                            &up->sg.grp);
    2515           0 :                                 snprintfrr(src_str, sizeof(src_str), "%pPAs",
    2516             :                                            &up->sg.src);
    2517           0 :                                 pim_time_uptime(uptime, sizeof(uptime),
    2518           0 :                                                 now - up->state_transition);
    2519             : 
    2520             :                                 /*
    2521             :                                  * Does this group live in json_fhr_sources?
    2522             :                                  * If not create it.
    2523             :                                  */
    2524           0 :                                 json_object_object_get_ex(json_fhr_sources,
    2525             :                                                           grp_str, &json_group);
    2526             : 
    2527           0 :                                 if (!json_group) {
    2528           0 :                                         json_group = json_object_new_object();
    2529           0 :                                         json_object_object_add(json_fhr_sources,
    2530             :                                                                grp_str,
    2531             :                                                                json_group);
    2532             :                                 }
    2533             : 
    2534           0 :                                 json_group_source = json_object_new_object();
    2535           0 :                                 json_object_string_add(json_group_source,
    2536             :                                                        "source", src_str);
    2537           0 :                                 json_object_string_add(json_group_source,
    2538             :                                                        "group", grp_str);
    2539           0 :                                 json_object_string_add(json_group_source,
    2540             :                                                        "upTime", uptime);
    2541           0 :                                 json_object_object_add(json_group, src_str,
    2542             :                                                        json_group_source);
    2543             :                         }
    2544             : 
    2545           0 :                         if (json_fhr_sources) {
    2546           0 :                                 json_object_object_add(json_row,
    2547             :                                                        "firstHopRouter",
    2548             :                                                        json_fhr_sources);
    2549             :                         }
    2550             : 
    2551           0 :                         json_object_int_add(json_row, "helloPeriod",
    2552           0 :                                             pim_ifp->pim_hello_period);
    2553           0 :                         json_object_int_add(json_row, "holdTime",
    2554           0 :                                             PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
    2555           0 :                         json_object_string_add(json_row, "helloTimer",
    2556             :                                                hello_timer);
    2557           0 :                         json_object_string_add(json_row, "helloStatStart",
    2558             :                                                stat_uptime);
    2559           0 :                         json_object_int_add(json_row, "helloReceived",
    2560           0 :                                             pim_ifp->pim_ifstat_hello_recv);
    2561           0 :                         json_object_int_add(json_row, "helloReceivedFailed",
    2562           0 :                                             pim_ifp->pim_ifstat_hello_recvfail);
    2563           0 :                         json_object_int_add(json_row, "helloSend",
    2564           0 :                                             pim_ifp->pim_ifstat_hello_sent);
    2565           0 :                         json_object_int_add(json_row, "hellosendFailed",
    2566           0 :                                             pim_ifp->pim_ifstat_hello_sendfail);
    2567           0 :                         json_object_int_add(json_row, "helloGenerationId",
    2568           0 :                                             pim_ifp->pim_generation_id);
    2569             : 
    2570           0 :                         json_object_int_add(
    2571             :                                 json_row, "effectivePropagationDelay",
    2572           0 :                                 pim_if_effective_propagation_delay_msec(ifp));
    2573           0 :                         json_object_int_add(
    2574             :                                 json_row, "effectiveOverrideInterval",
    2575           0 :                                 pim_if_effective_override_interval_msec(ifp));
    2576           0 :                         json_object_int_add(
    2577             :                                 json_row, "joinPruneOverrideInterval",
    2578           0 :                                 pim_if_jp_override_interval_msec(ifp));
    2579             : 
    2580           0 :                         json_object_int_add(
    2581             :                                 json_row, "propagationDelay",
    2582           0 :                                 pim_ifp->pim_propagation_delay_msec);
    2583           0 :                         json_object_int_add(
    2584             :                                 json_row, "propagationDelayHighest",
    2585           0 :                                 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
    2586           0 :                         json_object_int_add(
    2587             :                                 json_row, "overrideInterval",
    2588           0 :                                 pim_ifp->pim_override_interval_msec);
    2589           0 :                         json_object_int_add(
    2590             :                                 json_row, "overrideIntervalHighest",
    2591           0 :                                 pim_ifp->pim_neighbors_highest_override_interval_msec);
    2592           0 :                         if (pim_ifp->bsm_enable)
    2593           0 :                                 json_object_boolean_true_add(json_row,
    2594             :                                                              "bsmEnabled");
    2595           0 :                         if (pim_ifp->ucast_bsm_accept)
    2596           0 :                                 json_object_boolean_true_add(json_row,
    2597             :                                                              "ucastBsmEnabled");
    2598           0 :                         json_object_object_add(json, ifp->name, json_row);
    2599             : 
    2600             :                 } else {
    2601           0 :                         vty_out(vty, "Interface  : %s\n", ifp->name);
    2602           0 :                         vty_out(vty, "State      : %s\n",
    2603           0 :                                 if_is_up(ifp) ? "up" : "down");
    2604           0 :                         if (!pim_addr_is_any(pim_ifp->update_source)) {
    2605           0 :                                 vty_out(vty, "Use Source : %pPAs\n",
    2606             :                                         &pim_ifp->update_source);
    2607             :                         }
    2608           0 :                         if (pim_ifp->sec_addr_list) {
    2609           0 :                                 vty_out(vty, "Address    : %pPAs (primary)\n",
    2610             :                                         &ifaddr);
    2611           0 :                                 for (ALL_LIST_ELEMENTS_RO(
    2612             :                                              pim_ifp->sec_addr_list, sec_node,
    2613             :                                              sec_addr))
    2614           0 :                                         vty_out(vty, "             %pFX\n",
    2615             :                                                 &sec_addr->addr);
    2616             :                         } else {
    2617           0 :                                 vty_out(vty, "Address    : %pPAs\n", &ifaddr);
    2618             :                         }
    2619             : 
    2620           0 :                         if (pim_ifp->pim_passive_enable)
    2621           0 :                                 vty_out(vty, "Passive    : %s\n",
    2622             :                                         (pim_ifp->pim_passive_enable) ? "yes"
    2623             :                                                                       : "no");
    2624             : 
    2625           0 :                         vty_out(vty, "\n");
    2626             : 
    2627             :                         /* PIM neighbors */
    2628           0 :                         print_header = 1;
    2629             : 
    2630           0 :                         for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
    2631             :                                                   neighnode, neigh)) {
    2632             : 
    2633           0 :                                 if (print_header) {
    2634           0 :                                         vty_out(vty, "PIM Neighbors\n");
    2635           0 :                                         vty_out(vty, "-------------\n");
    2636           0 :                                         print_header = 0;
    2637             :                                 }
    2638             : 
    2639           0 :                                 snprintfrr(neigh_src_str, sizeof(neigh_src_str),
    2640             :                                            "%pPAs", &neigh->source_addr);
    2641           0 :                                 pim_time_uptime(uptime, sizeof(uptime),
    2642           0 :                                                 now - neigh->creation);
    2643           0 :                                 pim_time_timer_to_hhmmss(expire, sizeof(expire),
    2644             :                                                          neigh->t_expire_timer);
    2645           0 :                                 vty_out(vty,
    2646             :                                         "%-15s : up for %s, holdtime expires in %s\n",
    2647             :                                         neigh_src_str, uptime, expire);
    2648             :                         }
    2649             : 
    2650           0 :                         if (!print_header) {
    2651           0 :                                 vty_out(vty, "\n");
    2652           0 :                                 vty_out(vty, "\n");
    2653             :                         }
    2654             : 
    2655           0 :                         vty_out(vty, "Designated Router\n");
    2656           0 :                         vty_out(vty, "-----------------\n");
    2657           0 :                         vty_out(vty, "Address   : %s\n", dr_str);
    2658           0 :                         vty_out(vty, "Priority  : %u(%d)\n",
    2659             :                                 pim_ifp->pim_dr_priority,
    2660             :                                 pim_ifp->pim_dr_num_nondrpri_neighbors);
    2661           0 :                         vty_out(vty, "Uptime    : %s\n", dr_uptime);
    2662           0 :                         vty_out(vty, "Elections : %d\n",
    2663             :                                 pim_ifp->pim_dr_election_count);
    2664           0 :                         vty_out(vty, "Changes   : %d\n",
    2665             :                                 pim_ifp->pim_dr_election_changes);
    2666           0 :                         vty_out(vty, "\n");
    2667           0 :                         vty_out(vty, "\n");
    2668             : 
    2669             :                         /* FHR */
    2670           0 :                         print_header = 1;
    2671           0 :                         frr_each (rb_pim_upstream, &pim->upstream_head, up) {
    2672           0 :                                 if (!up->rpf.source_nexthop.interface)
    2673           0 :                                         continue;
    2674             : 
    2675           0 :                                 if (strcmp(ifp->name,
    2676             :                                            up->rpf.source_nexthop
    2677           0 :                                                    .interface->name) != 0)
    2678           0 :                                         continue;
    2679             : 
    2680           0 :                                 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
    2681           0 :                                         continue;
    2682             : 
    2683           0 :                                 if (print_header) {
    2684           0 :                                         vty_out(vty,
    2685             :                                                 "FHR - First Hop Router\n");
    2686           0 :                                         vty_out(vty,
    2687             :                                                 "----------------------\n");
    2688           0 :                                         print_header = 0;
    2689             :                                 }
    2690             : 
    2691           0 :                                 pim_time_uptime(uptime, sizeof(uptime),
    2692           0 :                                                 now - up->state_transition);
    2693           0 :                                 vty_out(vty,
    2694             :                                         "%pPAs : %pPAs is a source, uptime is %s\n",
    2695             :                                         &up->sg.grp, &up->sg.src, uptime);
    2696             :                         }
    2697             : 
    2698           0 :                         if (!print_header) {
    2699           0 :                                 vty_out(vty, "\n");
    2700           0 :                                 vty_out(vty, "\n");
    2701             :                         }
    2702             : 
    2703           0 :                         vty_out(vty, "Hellos\n");
    2704           0 :                         vty_out(vty, "------\n");
    2705           0 :                         vty_out(vty, "Period         : %d\n",
    2706             :                                 pim_ifp->pim_hello_period);
    2707           0 :                         vty_out(vty, "HoldTime       : %d\n",
    2708           0 :                                 PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
    2709           0 :                         vty_out(vty, "Timer          : %s\n", hello_timer);
    2710           0 :                         vty_out(vty, "StatStart      : %s\n", stat_uptime);
    2711           0 :                         vty_out(vty, "Receive        : %d\n",
    2712             :                                 pim_ifp->pim_ifstat_hello_recv);
    2713           0 :                         vty_out(vty, "Receive Failed : %d\n",
    2714             :                                 pim_ifp->pim_ifstat_hello_recvfail);
    2715           0 :                         vty_out(vty, "Send           : %d\n",
    2716             :                                 pim_ifp->pim_ifstat_hello_sent);
    2717           0 :                         vty_out(vty, "Send Failed    : %d\n",
    2718             :                                 pim_ifp->pim_ifstat_hello_sendfail);
    2719           0 :                         vty_out(vty, "Generation ID  : %08x\n",
    2720             :                                 pim_ifp->pim_generation_id);
    2721           0 :                         vty_out(vty, "\n");
    2722           0 :                         vty_out(vty, "\n");
    2723             : 
    2724           0 :                         pim_print_ifp_flags(vty, ifp);
    2725             : 
    2726           0 :                         vty_out(vty, "Join Prune Interval\n");
    2727           0 :                         vty_out(vty, "-------------------\n");
    2728           0 :                         vty_out(vty, "LAN Delay                    : %s\n",
    2729           0 :                                 pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
    2730           0 :                         vty_out(vty, "Effective Propagation Delay  : %d msec\n",
    2731           0 :                                 pim_if_effective_propagation_delay_msec(ifp));
    2732           0 :                         vty_out(vty, "Effective Override Interval  : %d msec\n",
    2733           0 :                                 pim_if_effective_override_interval_msec(ifp));
    2734           0 :                         vty_out(vty, "Join Prune Override Interval : %d msec\n",
    2735           0 :                                 pim_if_jp_override_interval_msec(ifp));
    2736           0 :                         vty_out(vty, "\n");
    2737           0 :                         vty_out(vty, "\n");
    2738             : 
    2739           0 :                         vty_out(vty, "LAN Prune Delay\n");
    2740           0 :                         vty_out(vty, "---------------\n");
    2741           0 :                         vty_out(vty, "Propagation Delay           : %d msec\n",
    2742           0 :                                 pim_ifp->pim_propagation_delay_msec);
    2743           0 :                         vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
    2744           0 :                                 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
    2745           0 :                         vty_out(vty, "Override Interval           : %d msec\n",
    2746           0 :                                 pim_ifp->pim_override_interval_msec);
    2747           0 :                         vty_out(vty, "Override Interval (Highest) : %d msec\n",
    2748           0 :                                 pim_ifp->pim_neighbors_highest_override_interval_msec);
    2749           0 :                         vty_out(vty, "\n");
    2750           0 :                         vty_out(vty, "\n");
    2751             : 
    2752           0 :                         vty_out(vty, "BSM Status\n");
    2753           0 :                         vty_out(vty, "----------\n");
    2754           0 :                         vty_out(vty, "Bsm Enabled          : %s\n",
    2755           0 :                                 pim_ifp->bsm_enable ? "yes" : "no");
    2756           0 :                         vty_out(vty, "Unicast Bsm Enabled  : %s\n",
    2757           0 :                                 pim_ifp->ucast_bsm_accept ? "yes" : "no");
    2758           0 :                         vty_out(vty, "\n");
    2759           0 :                         vty_out(vty, "\n");
    2760             :                 }
    2761             :         }
    2762             : 
    2763           0 :         if (!found_ifname)
    2764           0 :                 vty_out(vty, "%% No such interface\n");
    2765           0 : }
    2766             : 
    2767           0 : void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
    2768             :                                  bool uj)
    2769             : {
    2770           0 :         struct pim_ssm *ssm = pim->ssm_info;
    2771           0 :         const char *range_str =
    2772           0 :                 ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
    2773             : 
    2774           0 :         if (uj) {
    2775           0 :                 json_object *json;
    2776             : 
    2777           0 :                 json = json_object_new_object();
    2778           0 :                 json_object_string_add(json, "ssmGroups", range_str);
    2779           0 :                 vty_json(vty, json);
    2780             :         } else
    2781           0 :                 vty_out(vty, "SSM group range : %s\n", range_str);
    2782           0 : }
    2783             : 
    2784             : struct vty_pnc_cache_walk_data {
    2785             :         struct vty *vty;
    2786             :         struct pim_instance *pim;
    2787             : };
    2788             : 
    2789             : struct json_pnc_cache_walk_data {
    2790             :         json_object *json_obj;
    2791             :         struct pim_instance *pim;
    2792             : };
    2793             : 
    2794           0 : static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
    2795             : {
    2796           0 :         struct pim_nexthop_cache *pnc = bucket->data;
    2797           0 :         struct vty_pnc_cache_walk_data *cwd = arg;
    2798           0 :         struct vty *vty = cwd->vty;
    2799           0 :         struct pim_instance *pim = cwd->pim;
    2800           0 :         struct nexthop *nh_node = NULL;
    2801           0 :         ifindex_t first_ifindex;
    2802           0 :         struct interface *ifp = NULL;
    2803           0 :         struct ttable *tt = NULL;
    2804           0 :         char *table = NULL;
    2805             : 
    2806             :         /* Prepare table. */
    2807           0 :         tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    2808           0 :         ttable_add_row(tt, "Address|Interface|Nexthop");
    2809           0 :         tt->style.cell.rpad = 2;
    2810           0 :         tt->style.corner = '+';
    2811           0 :         ttable_restyle(tt);
    2812             : 
    2813           0 :         for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
    2814           0 :                 first_ifindex = nh_node->ifindex;
    2815             : 
    2816           0 :                 ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
    2817             : 
    2818             : #if PIM_IPV == 4
    2819           0 :                 ttable_add_row(tt, "%pPA|%s|%pI4", &pnc->rpf.rpf_addr,
    2820             :                                ifp ? ifp->name : "NULL", &nh_node->gate.ipv4);
    2821             : #else
    2822           0 :                 ttable_add_row(tt, "%pPA|%s|%pI6", &pnc->rpf.rpf_addr,
    2823             :                                ifp ? ifp->name : "NULL", &nh_node->gate.ipv6);
    2824             : #endif
    2825             :         }
    2826             :         /* Dump the generated table. */
    2827           0 :         table = ttable_dump(tt, "\n");
    2828           0 :         vty_out(vty, "%s\n", table);
    2829           0 :         XFREE(MTYPE_TMP, table);
    2830           0 :         ttable_del(tt);
    2831             : 
    2832           0 :         return CMD_SUCCESS;
    2833             : }
    2834             : 
    2835           0 : static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet,
    2836             :                                            void *arg)
    2837             : {
    2838           0 :         struct pim_nexthop_cache *pnc = backet->data;
    2839           0 :         struct json_pnc_cache_walk_data *cwd = arg;
    2840           0 :         struct pim_instance *pim = cwd->pim;
    2841           0 :         struct nexthop *nh_node = NULL;
    2842           0 :         ifindex_t first_ifindex;
    2843           0 :         struct interface *ifp = NULL;
    2844           0 :         char addr_str[PIM_ADDRSTRLEN];
    2845           0 :         json_object *json_row = NULL;
    2846           0 :         json_object *json_ifp = NULL;
    2847           0 :         json_object *json_arr = NULL;
    2848             : 
    2849           0 :         for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
    2850           0 :                 first_ifindex = nh_node->ifindex;
    2851           0 :                 ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
    2852           0 :                 snprintfrr(addr_str, sizeof(addr_str), "%pPA",
    2853             :                            &pnc->rpf.rpf_addr);
    2854           0 :                 json_object_object_get_ex(cwd->json_obj, addr_str, &json_row);
    2855           0 :                 if (!json_row) {
    2856           0 :                         json_row = json_object_new_object();
    2857           0 :                         json_object_string_addf(json_row, "address", "%pPA",
    2858             :                                                 &pnc->rpf.rpf_addr);
    2859           0 :                         json_object_object_addf(cwd->json_obj, json_row, "%pPA",
    2860             :                                                 &pnc->rpf.rpf_addr);
    2861           0 :                         json_arr = json_object_new_array();
    2862           0 :                         json_object_object_add(json_row, "nexthops", json_arr);
    2863             :                 }
    2864           0 :                 json_ifp = json_object_new_object();
    2865           0 :                 json_object_string_add(json_ifp, "interface",
    2866             :                                        ifp ? ifp->name : "NULL");
    2867             : #if PIM_IPV == 4
    2868           0 :                 json_object_string_addf(json_ifp, "nexthop", "%pI4",
    2869             :                                         &nh_node->gate.ipv4);
    2870             : #else
    2871           0 :                 json_object_string_addf(json_ifp, "nexthop", "%pI6",
    2872             :                                         &nh_node->gate.ipv6);
    2873             : #endif
    2874           0 :                 json_object_array_add(json_arr, json_ifp);
    2875             :         }
    2876           0 :         return CMD_SUCCESS;
    2877             : }
    2878             : 
    2879           0 : int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty,
    2880             :                                        pim_addr source, pim_addr group)
    2881             : {
    2882           0 :         int result = 0;
    2883           0 :         pim_addr vif_source;
    2884           0 :         struct prefix grp;
    2885           0 :         struct pim_nexthop nexthop;
    2886           0 :         struct vrf *v;
    2887           0 :         char grp_str[PREFIX_STRLEN];
    2888             : 
    2889           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    2890             : 
    2891           0 :         if (!v)
    2892             :                 return CMD_WARNING;
    2893             : 
    2894             : #if PIM_IPV == 4
    2895           0 :         if (pim_is_group_224_4(source)) {
    2896           0 :                 vty_out(vty,
    2897             :                         "Invalid argument. Expected Valid Source Address.\n");
    2898           0 :                 return CMD_WARNING;
    2899             :         }
    2900             : 
    2901           0 :         if (!pim_is_group_224_4(group)) {
    2902           0 :                 vty_out(vty,
    2903             :                         "Invalid argument. Expected Valid Multicast Group Address.\n");
    2904           0 :                 return CMD_WARNING;
    2905             :         }
    2906             : #endif
    2907             : 
    2908           0 :         if (!pim_rp_set_upstream_addr(v->info, &vif_source, source, group))
    2909             :                 return CMD_SUCCESS;
    2910             : 
    2911           0 :         pim_addr_to_prefix(&grp, group);
    2912           0 :         memset(&nexthop, 0, sizeof(nexthop));
    2913             : 
    2914           0 :         result =
    2915           0 :                 pim_ecmp_nexthop_lookup(v->info, &nexthop, vif_source, &grp, 0);
    2916             : 
    2917           0 :         if (!result) {
    2918           0 :                 vty_out(vty,
    2919             :                         "Nexthop Lookup failed, no usable routes returned.\n");
    2920           0 :                 return CMD_SUCCESS;
    2921             :         }
    2922             : 
    2923           0 :         pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str));
    2924             : 
    2925           0 :         vty_out(vty, "Group %s --- Nexthop %pPAs Interface %s\n", grp_str,
    2926           0 :                 &nexthop.mrib_nexthop_addr, nexthop.interface->name);
    2927             : 
    2928           0 :         return CMD_SUCCESS;
    2929             : }
    2930             : 
    2931           0 : int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty, bool uj)
    2932             : {
    2933           0 :         struct vrf *v;
    2934             : 
    2935           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    2936             : 
    2937           0 :         if (!v)
    2938             :                 return CMD_WARNING;
    2939             : 
    2940           0 :         pim_show_nexthop(v->info, vty, uj);
    2941             : 
    2942           0 :         return CMD_SUCCESS;
    2943             : }
    2944             : 
    2945           0 : void pim_show_nexthop(struct pim_instance *pim, struct vty *vty, bool uj)
    2946             : {
    2947           0 :         struct vty_pnc_cache_walk_data cwd;
    2948           0 :         struct json_pnc_cache_walk_data jcwd;
    2949             : 
    2950           0 :         cwd.vty = vty;
    2951           0 :         cwd.pim = pim;
    2952           0 :         jcwd.pim = pim;
    2953             : 
    2954           0 :         if (uj) {
    2955           0 :                 jcwd.json_obj = json_object_new_object();
    2956             :         } else {
    2957           0 :                 vty_out(vty, "Number of registered addresses: %lu\n",
    2958           0 :                         pim->rpf_hash->count);
    2959             :         }
    2960             : 
    2961           0 :         if (uj) {
    2962           0 :                 hash_walk(pim->rpf_hash, pim_print_json_pnc_cache_walkcb,
    2963             :                           &jcwd);
    2964           0 :                 vty_json(vty, jcwd.json_obj);
    2965             :         } else
    2966           0 :                 hash_walk(pim->rpf_hash, pim_print_vty_pnc_cache_walkcb, &cwd);
    2967           0 : }
    2968             : 
    2969          49 : int pim_show_neighbors_cmd_helper(const char *vrf, struct vty *vty,
    2970             :                                   const char *json, const char *interface)
    2971             : {
    2972          49 :         struct vrf *v;
    2973          49 :         json_object *json_parent = NULL;
    2974             : 
    2975          49 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    2976             : 
    2977          49 :         if (!v)
    2978             :                 return CMD_WARNING;
    2979             : 
    2980          49 :         if (json)
    2981          48 :                 json_parent = json_object_new_object();
    2982             : 
    2983          49 :         if (interface)
    2984           0 :                 pim_show_neighbors_single(v->info, vty, interface, json_parent);
    2985             :         else
    2986          49 :                 pim_show_neighbors(v->info, vty, json_parent);
    2987             : 
    2988          49 :         if (json)
    2989          48 :                 vty_json(vty, json_parent);
    2990             : 
    2991             :         return CMD_SUCCESS;
    2992             : }
    2993             : 
    2994           0 : int pim_show_neighbors_vrf_all_cmd_helper(struct vty *vty, const char *json,
    2995             :                                           const char *interface)
    2996             : {
    2997           0 :         struct vrf *v;
    2998           0 :         json_object *json_parent = NULL;
    2999           0 :         json_object *json_vrf = NULL;
    3000             : 
    3001           0 :         if (json)
    3002           0 :                 json_parent = json_object_new_object();
    3003           0 :         RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
    3004           0 :                 if (!json)
    3005           0 :                         vty_out(vty, "VRF: %s\n", v->name);
    3006             :                 else
    3007           0 :                         json_vrf = json_object_new_object();
    3008             : 
    3009           0 :                 if (interface)
    3010           0 :                         pim_show_neighbors_single(v->info, vty, interface,
    3011             :                                                   json_vrf);
    3012             :                 else
    3013           0 :                         pim_show_neighbors(v->info, vty, json_vrf);
    3014             : 
    3015           0 :                 if (json)
    3016           0 :                         json_object_object_add(json_parent, v->name, json_vrf);
    3017             :         }
    3018           0 :         if (json)
    3019           0 :                 vty_json(vty, json_parent);
    3020             : 
    3021           0 :         return CMD_SUCCESS;
    3022             : }
    3023             : 
    3024           0 : void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
    3025             :                                const char *neighbor, json_object *json)
    3026             : {
    3027           0 :         struct listnode *neighnode;
    3028           0 :         struct interface *ifp;
    3029           0 :         struct pim_interface *pim_ifp;
    3030           0 :         struct pim_neighbor *neigh;
    3031           0 :         time_t now;
    3032           0 :         int found_neighbor = 0;
    3033           0 :         int option_address_list;
    3034           0 :         int option_dr_priority;
    3035           0 :         int option_generation_id;
    3036           0 :         int option_holdtime;
    3037           0 :         int option_lan_prune_delay;
    3038           0 :         int option_t_bit;
    3039           0 :         char uptime[10];
    3040           0 :         char expire[10];
    3041           0 :         char neigh_src_str[PIM_ADDRSTRLEN];
    3042             : 
    3043           0 :         json_object *json_ifp = NULL;
    3044           0 :         json_object *json_row = NULL;
    3045             : 
    3046           0 :         now = pim_time_monotonic_sec();
    3047             : 
    3048           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    3049           0 :                 pim_ifp = ifp->info;
    3050             : 
    3051           0 :                 if (!pim_ifp)
    3052           0 :                         continue;
    3053             : 
    3054           0 :                 if (pim_ifp->pim_sock_fd < 0)
    3055           0 :                         continue;
    3056             : 
    3057           0 :                 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
    3058             :                                           neigh)) {
    3059           0 :                         snprintfrr(neigh_src_str, sizeof(neigh_src_str),
    3060             :                                    "%pPAs", &neigh->source_addr);
    3061             : 
    3062             :                         /*
    3063             :                          * The user can specify either the interface name or the
    3064             :                          * PIM neighbor IP.
    3065             :                          * If this pim_ifp matches neither then skip.
    3066             :                          */
    3067           0 :                         if (strcmp(neighbor, "detail") &&
    3068           0 :                             strcmp(neighbor, ifp->name) &&
    3069           0 :                             strcmp(neighbor, neigh_src_str))
    3070           0 :                                 continue;
    3071             : 
    3072           0 :                         found_neighbor = 1;
    3073           0 :                         pim_time_uptime(uptime, sizeof(uptime),
    3074           0 :                                         now - neigh->creation);
    3075           0 :                         pim_time_timer_to_hhmmss(expire, sizeof(expire),
    3076             :                                                  neigh->t_expire_timer);
    3077             : 
    3078           0 :                         option_address_list = 0;
    3079           0 :                         option_dr_priority = 0;
    3080           0 :                         option_generation_id = 0;
    3081           0 :                         option_holdtime = 0;
    3082           0 :                         option_lan_prune_delay = 0;
    3083           0 :                         option_t_bit = 0;
    3084             : 
    3085           0 :                         if (PIM_OPTION_IS_SET(neigh->hello_options,
    3086             :                                               PIM_OPTION_MASK_ADDRESS_LIST))
    3087           0 :                                 option_address_list = 1;
    3088             : 
    3089           0 :                         if (PIM_OPTION_IS_SET(neigh->hello_options,
    3090             :                                               PIM_OPTION_MASK_DR_PRIORITY))
    3091           0 :                                 option_dr_priority = 1;
    3092             : 
    3093           0 :                         if (PIM_OPTION_IS_SET(neigh->hello_options,
    3094             :                                               PIM_OPTION_MASK_GENERATION_ID))
    3095           0 :                                 option_generation_id = 1;
    3096             : 
    3097           0 :                         if (PIM_OPTION_IS_SET(neigh->hello_options,
    3098             :                                               PIM_OPTION_MASK_HOLDTIME))
    3099           0 :                                 option_holdtime = 1;
    3100             : 
    3101           0 :                         if (PIM_OPTION_IS_SET(neigh->hello_options,
    3102             :                                               PIM_OPTION_MASK_LAN_PRUNE_DELAY))
    3103           0 :                                 option_lan_prune_delay = 1;
    3104             : 
    3105           0 :                         if (PIM_OPTION_IS_SET(
    3106             :                                     neigh->hello_options,
    3107             :                                     PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
    3108           0 :                                 option_t_bit = 1;
    3109             : 
    3110           0 :                         if (json) {
    3111             : 
    3112             :                                 /* Does this ifp live in json? If not create it
    3113             :                                  */
    3114           0 :                                 json_object_object_get_ex(json, ifp->name,
    3115             :                                                           &json_ifp);
    3116             : 
    3117           0 :                                 if (!json_ifp) {
    3118           0 :                                         json_ifp = json_object_new_object();
    3119           0 :                                         json_object_pim_ifp_add(json_ifp, ifp);
    3120           0 :                                         json_object_object_add(json, ifp->name,
    3121             :                                                                json_ifp);
    3122             :                                 }
    3123             : 
    3124           0 :                                 json_row = json_object_new_object();
    3125           0 :                                 json_object_string_add(json_row, "interface",
    3126             :                                                        ifp->name);
    3127           0 :                                 json_object_string_add(json_row, "address",
    3128             :                                                        neigh_src_str);
    3129           0 :                                 json_object_string_add(json_row, "upTime",
    3130             :                                                        uptime);
    3131           0 :                                 json_object_string_add(json_row, "holdtime",
    3132             :                                                        expire);
    3133           0 :                                 json_object_int_add(json_row, "drPriority",
    3134           0 :                                                     neigh->dr_priority);
    3135           0 :                                 json_object_int_add(json_row, "generationId",
    3136           0 :                                                     neigh->generation_id);
    3137             : 
    3138           0 :                                 if (option_address_list)
    3139           0 :                                         json_object_boolean_true_add(
    3140             :                                                 json_row,
    3141             :                                                 "helloOptionAddressList");
    3142             : 
    3143           0 :                                 if (option_dr_priority)
    3144           0 :                                         json_object_boolean_true_add(
    3145             :                                                 json_row,
    3146             :                                                 "helloOptionDrPriority");
    3147             : 
    3148           0 :                                 if (option_generation_id)
    3149           0 :                                         json_object_boolean_true_add(
    3150             :                                                 json_row,
    3151             :                                                 "helloOptionGenerationId");
    3152             : 
    3153           0 :                                 if (option_holdtime)
    3154           0 :                                         json_object_boolean_true_add(
    3155             :                                                 json_row,
    3156             :                                                 "helloOptionHoldtime");
    3157             : 
    3158           0 :                                 if (option_lan_prune_delay)
    3159           0 :                                         json_object_boolean_true_add(
    3160             :                                                 json_row,
    3161             :                                                 "helloOptionLanPruneDelay");
    3162             : 
    3163           0 :                                 if (option_t_bit)
    3164           0 :                                         json_object_boolean_true_add(
    3165             :                                                 json_row, "helloOptionTBit");
    3166             : 
    3167           0 :                                 json_object_object_add(json_ifp, neigh_src_str,
    3168             :                                                        json_row);
    3169             : 
    3170             :                         } else {
    3171           0 :                                 vty_out(vty, "Interface : %s\n", ifp->name);
    3172           0 :                                 vty_out(vty, "Neighbor  : %s\n", neigh_src_str);
    3173           0 :                                 vty_out(vty,
    3174             :                                         "    Uptime                         : %s\n",
    3175             :                                         uptime);
    3176           0 :                                 vty_out(vty,
    3177             :                                         "    Holdtime                       : %s\n",
    3178             :                                         expire);
    3179           0 :                                 vty_out(vty,
    3180             :                                         "    DR Priority                    : %d\n",
    3181             :                                         neigh->dr_priority);
    3182           0 :                                 vty_out(vty,
    3183             :                                         "    Generation ID                  : %08x\n",
    3184             :                                         neigh->generation_id);
    3185           0 :                                 vty_out(vty,
    3186             :                                         "    Override Interval (msec)       : %d\n",
    3187           0 :                                         neigh->override_interval_msec);
    3188           0 :                                 vty_out(vty,
    3189             :                                         "    Propagation Delay (msec)       : %d\n",
    3190           0 :                                         neigh->propagation_delay_msec);
    3191           0 :                                 vty_out(vty,
    3192             :                                         "    Hello Option - Address List    : %s\n",
    3193             :                                         option_address_list ? "yes" : "no");
    3194           0 :                                 vty_out(vty,
    3195             :                                         "    Hello Option - DR Priority     : %s\n",
    3196             :                                         option_dr_priority ? "yes" : "no");
    3197           0 :                                 vty_out(vty,
    3198             :                                         "    Hello Option - Generation ID   : %s\n",
    3199             :                                         option_generation_id ? "yes" : "no");
    3200           0 :                                 vty_out(vty,
    3201             :                                         "    Hello Option - Holdtime        : %s\n",
    3202             :                                         option_holdtime ? "yes" : "no");
    3203           0 :                                 vty_out(vty,
    3204             :                                         "    Hello Option - LAN Prune Delay : %s\n",
    3205             :                                         option_lan_prune_delay ? "yes" : "no");
    3206           0 :                                 vty_out(vty,
    3207             :                                         "    Hello Option - T-bit           : %s\n",
    3208             :                                         option_t_bit ? "yes" : "no");
    3209           0 :                                 bfd_sess_show(vty, json_ifp,
    3210             :                                               neigh->bfd_session);
    3211           0 :                                 vty_out(vty, "\n");
    3212             :                         }
    3213             :                 }
    3214             :         }
    3215             : 
    3216           0 :         if (!found_neighbor)
    3217           0 :                 vty_out(vty, "%% No such interface or neighbor\n");
    3218           0 : }
    3219             : 
    3220          49 : void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
    3221             :                         json_object *json)
    3222             : {
    3223          49 :         struct listnode *neighnode;
    3224          49 :         struct interface *ifp;
    3225          49 :         struct pim_interface *pim_ifp;
    3226          49 :         struct pim_neighbor *neigh;
    3227          49 :         struct ttable *tt = NULL;
    3228          49 :         char *table = NULL;
    3229          49 :         time_t now;
    3230          49 :         char uptime[10];
    3231          49 :         char expire[10];
    3232          49 :         char neigh_src_str[PIM_ADDRSTRLEN];
    3233          49 :         json_object *json_ifp_rows = NULL;
    3234          49 :         json_object *json_row = NULL;
    3235             : 
    3236          49 :         now = pim_time_monotonic_sec();
    3237             : 
    3238          49 :         if (!json) {
    3239             :                 /* Prepare table. */
    3240           1 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    3241           1 :                 ttable_add_row(tt, "Interface|Neighbor|Uptime|Holdtime|DR Pri");
    3242           1 :                 tt->style.cell.rpad = 2;
    3243           1 :                 tt->style.corner = '+';
    3244           1 :                 ttable_restyle(tt);
    3245             :         }
    3246             : 
    3247         303 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    3248         205 :                 pim_ifp = ifp->info;
    3249             : 
    3250         205 :                 if (!pim_ifp)
    3251          48 :                         continue;
    3252             : 
    3253         157 :                 if (pim_ifp->pim_sock_fd < 0)
    3254          51 :                         continue;
    3255             : 
    3256         106 :                 if (json)
    3257         104 :                         json_ifp_rows = json_object_new_object();
    3258             : 
    3259         290 :                 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
    3260             :                                           neigh)) {
    3261          78 :                         snprintfrr(neigh_src_str, sizeof(neigh_src_str),
    3262             :                                    "%pPAs", &neigh->source_addr);
    3263          78 :                         pim_time_uptime(uptime, sizeof(uptime),
    3264          78 :                                         now - neigh->creation);
    3265          78 :                         pim_time_timer_to_hhmmss(expire, sizeof(expire),
    3266             :                                                  neigh->t_expire_timer);
    3267             : 
    3268          78 :                         if (json) {
    3269          78 :                                 json_row = json_object_new_object();
    3270          78 :                                 json_object_string_add(json_row, "interface",
    3271          78 :                                                        ifp->name);
    3272          78 :                                 json_object_string_add(json_row, "neighbor",
    3273             :                                                        neigh_src_str);
    3274          78 :                                 json_object_string_add(json_row, "upTime",
    3275             :                                                        uptime);
    3276          78 :                                 json_object_string_add(json_row, "holdTime",
    3277             :                                                        expire);
    3278          78 :                                 json_object_int_add(json_row, "holdTimeMax",
    3279          78 :                                                     neigh->holdtime);
    3280          78 :                                 json_object_int_add(json_row, "drPriority",
    3281          78 :                                                     neigh->dr_priority);
    3282          78 :                                 json_object_object_add(json_ifp_rows,
    3283             :                                                        neigh_src_str, json_row);
    3284             : 
    3285             :                         } else {
    3286           0 :                                 ttable_add_row(tt, "%s|%pPAs|%s|%s|%d",
    3287           0 :                                                ifp->name, &neigh->source_addr,
    3288             :                                                uptime, expire,
    3289             :                                                neigh->dr_priority);
    3290             :                         }
    3291             :                 }
    3292             : 
    3293         106 :                 if (json) {
    3294         104 :                         json_object_object_add(json, ifp->name, json_ifp_rows);
    3295         104 :                         json_ifp_rows = NULL;
    3296             :                 }
    3297             :         }
    3298             :         /* Dump the generated table. */
    3299          49 :         if (!json) {
    3300           1 :                 table = ttable_dump(tt, "\n");
    3301           1 :                 vty_out(vty, "%s\n", table);
    3302           1 :                 XFREE(MTYPE_TMP, table);
    3303           1 :                 ttable_del(tt);
    3304             :         }
    3305          49 : }
    3306             : 
    3307           8 : int gm_process_query_max_response_time_cmd(struct vty *vty,
    3308             :                                            const char *qmrt_str)
    3309             : {
    3310           8 :         const struct lyd_node *pim_enable_dnode;
    3311             : 
    3312          16 :         pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
    3313           8 :                                            FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
    3314             :                                            FRR_PIM_AF_XPATH_VAL);
    3315             : 
    3316           8 :         if (!pim_enable_dnode) {
    3317           0 :                 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
    3318             :         } else {
    3319           8 :                 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
    3320           0 :                         nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
    3321             :                                               "true");
    3322             :         }
    3323             : 
    3324           8 :         nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
    3325             :                               qmrt_str);
    3326           8 :         return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
    3327             :                                     FRR_PIM_AF_XPATH_VAL);
    3328             : }
    3329             : 
    3330           0 : int gm_process_no_query_max_response_time_cmd(struct vty *vty)
    3331             : {
    3332           0 :         nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_DESTROY,
    3333             :                               NULL);
    3334           0 :         return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
    3335             :                                     FRR_PIM_AF_XPATH_VAL);
    3336             : }
    3337             : 
    3338           0 : int gm_process_last_member_query_count_cmd(struct vty *vty,
    3339             :                                            const char *lmqc_str)
    3340             : {
    3341           0 :         const struct lyd_node *pim_enable_dnode;
    3342             : 
    3343           0 :         pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
    3344           0 :                                            FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
    3345             :                                            FRR_PIM_AF_XPATH_VAL);
    3346           0 :         if (!pim_enable_dnode) {
    3347           0 :                 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
    3348             :         } else {
    3349           0 :                 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
    3350           0 :                         nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
    3351             :                                               "true");
    3352             :         }
    3353             : 
    3354           0 :         nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
    3355             :                               lmqc_str);
    3356           0 :         return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
    3357             :                                     FRR_PIM_AF_XPATH_VAL);
    3358             : }
    3359             : 
    3360           0 : int gm_process_no_last_member_query_count_cmd(struct vty *vty)
    3361             : {
    3362           0 :         nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_DESTROY,
    3363             :                               NULL);
    3364           0 :         return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
    3365             :                                     FRR_PIM_AF_XPATH_VAL);
    3366             : }
    3367             : 
    3368           0 : int gm_process_last_member_query_interval_cmd(struct vty *vty,
    3369             :                                               const char *lmqi_str)
    3370             : {
    3371           0 :         const struct lyd_node *pim_enable_dnode;
    3372             : 
    3373           0 :         pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
    3374           0 :                                            FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
    3375             :                                            FRR_PIM_AF_XPATH_VAL);
    3376           0 :         if (!pim_enable_dnode) {
    3377           0 :                 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
    3378             :         } else {
    3379           0 :                 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
    3380           0 :                         nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
    3381             :                                               "true");
    3382             :         }
    3383             : 
    3384           0 :         nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
    3385             :                               lmqi_str);
    3386           0 :         return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
    3387             :                                     FRR_PIM_AF_XPATH_VAL);
    3388             : }
    3389             : 
    3390           0 : int gm_process_no_last_member_query_interval_cmd(struct vty *vty)
    3391             : {
    3392           0 :         nb_cli_enqueue_change(vty, "./last-member-query-interval",
    3393             :                               NB_OP_DESTROY, NULL);
    3394           0 :         return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
    3395             :                                     FRR_PIM_AF_XPATH_VAL);
    3396             : }
    3397             : 
    3398           0 : int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation,
    3399             :                              const char *src_str)
    3400             : {
    3401           0 :         const char *vrfname;
    3402           0 :         char ssmpingd_ip_xpath[XPATH_MAXLEN];
    3403             : 
    3404           0 :         vrfname = pim_cli_get_vrf_name(vty);
    3405           0 :         if (vrfname == NULL)
    3406             :                 return CMD_WARNING_CONFIG_FAILED;
    3407             : 
    3408           0 :         snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
    3409             :                  FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
    3410             :                  FRR_PIM_AF_XPATH_VAL);
    3411           0 :         strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
    3412             :                 sizeof(ssmpingd_ip_xpath));
    3413             : 
    3414           0 :         nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, operation, src_str);
    3415             : 
    3416           0 :         return nb_cli_apply_changes(vty, NULL);
    3417             : }
    3418             : 
    3419           0 : int pim_process_bsm_cmd(struct vty *vty)
    3420             : {
    3421           0 :         const struct lyd_node *gm_enable_dnode;
    3422             : 
    3423           0 :         gm_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
    3424           0 :                                           FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
    3425             :                                           FRR_PIM_AF_XPATH_VAL);
    3426           0 :         if (!gm_enable_dnode)
    3427           0 :                 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
    3428             :                                       "true");
    3429             :         else {
    3430           0 :                 if (!yang_dnode_get_bool(gm_enable_dnode, "."))
    3431           0 :                         nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
    3432             :                                               "true");
    3433             :         }
    3434             : 
    3435           0 :         nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "true");
    3436             : 
    3437           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
    3438             :                                     FRR_PIM_AF_XPATH_VAL);
    3439             : }
    3440             : 
    3441           0 : int pim_process_no_bsm_cmd(struct vty *vty)
    3442             : {
    3443           0 :         nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "false");
    3444             : 
    3445           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
    3446             :                                     FRR_PIM_AF_XPATH_VAL);
    3447             : }
    3448             : 
    3449           0 : int pim_process_unicast_bsm_cmd(struct vty *vty)
    3450             : {
    3451           0 :         const struct lyd_node *gm_enable_dnode;
    3452             : 
    3453           0 :         gm_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
    3454           0 :                                           FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
    3455             :                                           FRR_PIM_AF_XPATH_VAL);
    3456           0 :         if (!gm_enable_dnode)
    3457           0 :                 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
    3458             :                                       "true");
    3459             :         else {
    3460           0 :                 if (!yang_dnode_get_bool(gm_enable_dnode, "."))
    3461           0 :                         nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
    3462             :                                               "true");
    3463             :         }
    3464             : 
    3465           0 :         nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "true");
    3466             : 
    3467           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
    3468             :                                     FRR_PIM_AF_XPATH_VAL);
    3469             : }
    3470             : 
    3471           0 : int pim_process_no_unicast_bsm_cmd(struct vty *vty)
    3472             : {
    3473           0 :         nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "false");
    3474             : 
    3475           0 :         return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
    3476             :                                     FRR_PIM_AF_XPATH_VAL);
    3477             : }
    3478             : 
    3479           0 : static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
    3480             :                                 time_t now)
    3481             : {
    3482           0 :         char uptime_scan_oil[10];
    3483           0 :         char uptime_mroute_add[10];
    3484           0 :         char uptime_mroute_del[10];
    3485             : 
    3486           0 :         pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
    3487             :                               pim->scan_oil_last);
    3488           0 :         pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
    3489             :                               pim->mroute_add_last);
    3490           0 :         pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
    3491             :                               pim->mroute_del_last);
    3492             : 
    3493           0 :         vty_out(vty,
    3494             :                 "Scan OIL - Last: %s  Events: %lld\n"
    3495             :                 "MFC Add  - Last: %s  Events: %lld\n"
    3496             :                 "MFC Del  - Last: %s  Events: %lld\n",
    3497           0 :                 uptime_scan_oil, (long long)pim->scan_oil_events,
    3498           0 :                 uptime_mroute_add, (long long)pim->mroute_add_events,
    3499           0 :                 uptime_mroute_del, (long long)pim->mroute_del_events);
    3500           0 : }
    3501             : 
    3502           0 : void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
    3503             :                                json_object *json)
    3504             : {
    3505           0 :         struct interface *ifp;
    3506           0 :         struct ttable *tt = NULL;
    3507           0 :         char *table = NULL;
    3508           0 :         json_object *json_row = NULL;
    3509             : 
    3510           0 :         vty_out(vty, "\n");
    3511             : 
    3512           0 :         if (!json) {
    3513             :                 /* Prepare table. */
    3514           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    3515           0 :                 ttable_add_row(
    3516             :                         tt,
    3517             :                         "Interface|Address|ifi|Vif|PktsIn|PktsOut|BytesIn|BytesOut");
    3518           0 :                 tt->style.cell.rpad = 2;
    3519           0 :                 tt->style.corner = '+';
    3520           0 :                 ttable_restyle(tt);
    3521             :         }
    3522             : 
    3523           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    3524           0 :                 struct pim_interface *pim_ifp;
    3525             : #if PIM_IPV == 4
    3526           0 :                 struct sioc_vif_req vreq;
    3527             : #else
    3528           0 :                 struct sioc_mif_req6 vreq;
    3529             : #endif
    3530             : 
    3531           0 :                 pim_ifp = ifp->info;
    3532             : 
    3533           0 :                 if (!pim_ifp)
    3534           0 :                         continue;
    3535             : 
    3536           0 :                 memset(&vreq, 0, sizeof(vreq));
    3537             : #if PIM_IPV == 4
    3538           0 :                 vreq.vifi = pim_ifp->mroute_vif_index;
    3539           0 :                 if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
    3540           0 :                         zlog_warn(
    3541             :                                 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
    3542             :                                 (unsigned long)SIOCGETVIFCNT, ifp->name,
    3543             :                                 pim_ifp->mroute_vif_index, errno,
    3544             :                                 safe_strerror(errno));
    3545             :                 }
    3546             : #else
    3547           0 :                 vreq.mifi = pim_ifp->mroute_vif_index;
    3548           0 :                 if (ioctl(pim->mroute_socket, SIOCGETMIFCNT_IN6, &vreq)) {
    3549           0 :                         zlog_warn(
    3550             :                                 "ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
    3551             :                                 (unsigned long)SIOCGETMIFCNT_IN6, ifp->name,
    3552             :                                 pim_ifp->mroute_vif_index, errno,
    3553             :                                 safe_strerror(errno));
    3554             :                 }
    3555             : #endif
    3556             : 
    3557           0 :                 if (json) {
    3558           0 :                         json_row = json_object_new_object();
    3559           0 :                         json_object_string_add(json_row, "name", ifp->name);
    3560           0 :                         json_object_string_add(json_row, "state",
    3561           0 :                                                if_is_up(ifp) ? "up" : "down");
    3562           0 :                         json_object_string_addf(json_row, "address", "%pPA",
    3563             :                                                 &pim_ifp->primary_address);
    3564           0 :                         json_object_int_add(json_row, "ifIndex", ifp->ifindex);
    3565           0 :                         json_object_int_add(json_row, "vif",
    3566           0 :                                             pim_ifp->mroute_vif_index);
    3567           0 :                         json_object_int_add(json_row, "pktsIn",
    3568           0 :                                             (unsigned long)vreq.icount);
    3569           0 :                         json_object_int_add(json_row, "pktsOut",
    3570           0 :                                             (unsigned long)vreq.ocount);
    3571           0 :                         json_object_int_add(json_row, "bytesIn",
    3572           0 :                                             (unsigned long)vreq.ibytes);
    3573           0 :                         json_object_int_add(json_row, "bytesOut",
    3574           0 :                                             (unsigned long)vreq.obytes);
    3575           0 :                         json_object_object_add(json, ifp->name, json_row);
    3576             :                 } else {
    3577           0 :                         ttable_add_row(tt, "%s|%pPAs|%d|%d|%lu|%lu|%lu|%lu",
    3578           0 :                                        ifp->name, &pim_ifp->primary_address,
    3579             :                                        ifp->ifindex, pim_ifp->mroute_vif_index,
    3580             :                                        (unsigned long)vreq.icount,
    3581             :                                        (unsigned long)vreq.ocount,
    3582             :                                        (unsigned long)vreq.ibytes,
    3583             :                                        (unsigned long)vreq.obytes);
    3584             :                 }
    3585             :         }
    3586             :         /* Dump the generated table. */
    3587           0 :         if (!json) {
    3588           0 :                 table = ttable_dump(tt, "\n");
    3589           0 :                 vty_out(vty, "%s\n", table);
    3590           0 :                 XFREE(MTYPE_TMP, table);
    3591           0 :                 ttable_del(tt);
    3592             :         }
    3593           0 : }
    3594             : 
    3595           0 : void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
    3596             : {
    3597           0 :         struct vrf *vrf = pim->vrf;
    3598           0 :         time_t now = pim_time_monotonic_sec();
    3599           0 :         char uptime[10];
    3600           0 :         char mlag_role[80];
    3601             : 
    3602           0 :         pim = vrf->info;
    3603             : 
    3604           0 :         vty_out(vty, "Router MLAG Role: %s\n",
    3605           0 :                 mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
    3606           0 :         vty_out(vty, "Mroute socket descriptor:");
    3607             : 
    3608           0 :         vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
    3609           0 :         vty_out(vty, "PIM Register socket descriptor:");
    3610           0 :         vty_out(vty, " %d(%s)\n", pim->reg_sock, vrf->name);
    3611             : 
    3612           0 :         pim_time_uptime(uptime, sizeof(uptime),
    3613           0 :                         now - pim->mroute_socket_creation);
    3614           0 :         vty_out(vty, "Mroute socket uptime: %s\n", uptime);
    3615             : 
    3616           0 :         vty_out(vty, "\n");
    3617             : 
    3618           0 :         pim_zebra_zclient_update(vty);
    3619           0 :         pim_zlookup_show_ip_multicast(vty);
    3620             : 
    3621           0 :         vty_out(vty, "\n");
    3622           0 :         vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
    3623             : 
    3624           0 :         vty_out(vty, "\n");
    3625           0 :         vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
    3626           0 :         vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
    3627           0 :         vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
    3628           0 :         vty_out(vty, "PIM ECMP Rebalance: %s\n",
    3629           0 :                 pim->ecmp_rebalance_enable ? "Enable" : "Disable");
    3630             : 
    3631           0 :         vty_out(vty, "\n");
    3632             : 
    3633           0 :         pim_show_rpf_refresh_stats(vty, pim, now, NULL);
    3634             : 
    3635           0 :         vty_out(vty, "\n");
    3636             : 
    3637           0 :         show_scan_oil_stats(pim, vty, now);
    3638             : 
    3639           0 :         show_multicast_interfaces(pim, vty, NULL);
    3640           0 : }
    3641             : 
    3642          14 : void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
    3643             :                  bool fill, json_object *json)
    3644             : {
    3645          14 :         struct listnode *node;
    3646          14 :         struct channel_oil *c_oil;
    3647          14 :         struct static_route *s_route;
    3648          14 :         struct ttable *tt = NULL;
    3649          14 :         char *table = NULL;
    3650          14 :         time_t now;
    3651          14 :         json_object *json_group = NULL;
    3652          14 :         json_object *json_source = NULL;
    3653          14 :         json_object *json_oil = NULL;
    3654          14 :         json_object *json_ifp_out = NULL;
    3655          14 :         int found_oif;
    3656          14 :         int first;
    3657          14 :         char grp_str[PIM_ADDRSTRLEN];
    3658          14 :         char src_str[PIM_ADDRSTRLEN];
    3659          14 :         char in_ifname[INTERFACE_NAMSIZ + 1];
    3660          14 :         char out_ifname[INTERFACE_NAMSIZ + 1];
    3661          14 :         int oif_vif_index;
    3662          14 :         struct interface *ifp_in;
    3663          14 :         char proto[100];
    3664          14 :         char state_str[PIM_REG_STATE_STR_LEN];
    3665          14 :         char mroute_uptime[10];
    3666             : 
    3667          14 :         if (!json) {
    3668           0 :                 vty_out(vty, "IP Multicast Routing Table\n");
    3669           0 :                 vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
    3670           0 :                 vty_out(vty,
    3671             :                         "       R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
    3672             : 
    3673             :                 /* Prepare table. */
    3674           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    3675           0 :                 ttable_add_row(
    3676             :                         tt, "Source|Group|Flags|Proto|Input|Output|TTL|Uptime");
    3677           0 :                 tt->style.cell.rpad = 2;
    3678           0 :                 tt->style.corner = '+';
    3679           0 :                 ttable_restyle(tt);
    3680             :         }
    3681             : 
    3682          14 :         now = pim_time_monotonic_sec();
    3683             : 
    3684             :         /* print list of PIM and IGMP routes */
    3685          56 :         frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
    3686          14 :                 found_oif = 0;
    3687          14 :                 first = 1;
    3688          14 :                 if (!c_oil->installed)
    3689           1 :                         continue;
    3690             : 
    3691          13 :                 if (!pim_addr_is_any(sg->grp) &&
    3692           0 :                     pim_addr_cmp(sg->grp, *oil_mcastgrp(c_oil)))
    3693           0 :                         continue;
    3694          13 :                 if (!pim_addr_is_any(sg->src) &&
    3695           0 :                     pim_addr_cmp(sg->src, *oil_origin(c_oil)))
    3696           0 :                         continue;
    3697             : 
    3698          13 :                 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
    3699             :                            oil_mcastgrp(c_oil));
    3700          13 :                 snprintfrr(src_str, sizeof(src_str), "%pPAs",
    3701             :                            oil_origin(c_oil));
    3702             : 
    3703          13 :                 strlcpy(state_str, "S", sizeof(state_str));
    3704             :                 /* When a non DR receives a igmp join, it creates a (*,G)
    3705             :                  * channel_oil without any upstream creation
    3706             :                  */
    3707          13 :                 if (c_oil->up) {
    3708          13 :                         if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
    3709           0 :                                 strlcat(state_str, "C", sizeof(state_str));
    3710          13 :                         if (pim_upstream_is_sg_rpt(c_oil->up))
    3711           0 :                                 strlcat(state_str, "R", sizeof(state_str));
    3712          13 :                         if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
    3713           1 :                                 strlcat(state_str, "F", sizeof(state_str));
    3714          13 :                         if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
    3715          13 :                                 strlcat(state_str, "T", sizeof(state_str));
    3716             :                 }
    3717          13 :                 if (pim_channel_oil_empty(c_oil))
    3718          11 :                         strlcat(state_str, "P", sizeof(state_str));
    3719             : 
    3720          13 :                 ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
    3721             : 
    3722          13 :                 if (ifp_in)
    3723          13 :                         strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
    3724             :                 else
    3725           0 :                         strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
    3726             : 
    3727             : 
    3728          13 :                 pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
    3729          13 :                                 now - c_oil->mroute_creation);
    3730             : 
    3731          13 :                 if (json) {
    3732             : 
    3733             :                         /* Find the group, create it if it doesn't exist */
    3734          13 :                         json_object_object_get_ex(json, grp_str, &json_group);
    3735             : 
    3736          13 :                         if (!json_group) {
    3737          13 :                                 json_group = json_object_new_object();
    3738          13 :                                 json_object_object_add(json, grp_str,
    3739             :                                                        json_group);
    3740             :                         }
    3741             : 
    3742             :                         /* Find the source nested under the group, create it if
    3743             :                          * it doesn't exist
    3744             :                          */
    3745          13 :                         json_object_object_get_ex(json_group, src_str,
    3746             :                                                   &json_source);
    3747             : 
    3748          13 :                         if (!json_source) {
    3749          13 :                                 json_source = json_object_new_object();
    3750          13 :                                 json_object_object_add(json_group, src_str,
    3751             :                                                        json_source);
    3752             :                         }
    3753             : 
    3754             :                         /* Find the inbound interface nested under the source,
    3755             :                          * create it if it doesn't exist
    3756             :                          */
    3757          13 :                         json_object_string_add(json_source, "source", src_str);
    3758          13 :                         json_object_string_add(json_source, "group", grp_str);
    3759          13 :                         json_object_int_add(json_source, "installed",
    3760          13 :                                             c_oil->installed);
    3761          13 :                         json_object_int_add(json_source, "refCount",
    3762          13 :                                             c_oil->oil_ref_count);
    3763          13 :                         json_object_int_add(json_source, "oilSize",
    3764          13 :                                             c_oil->oil_size);
    3765          13 :                         json_object_int_add(json_source, "oilInheritedRescan",
    3766          13 :                                             c_oil->oil_inherited_rescan);
    3767          13 :                         json_object_string_add(json_source, "iif", in_ifname);
    3768          13 :                         json_object_string_add(json_source, "upTime",
    3769             :                                                mroute_uptime);
    3770          13 :                         json_oil = NULL;
    3771             :                 }
    3772             : 
    3773        3341 :                 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
    3774        3328 :                      ++oif_vif_index) {
    3775        3328 :                         struct interface *ifp_out;
    3776        3328 :                         int ttl;
    3777             : 
    3778        3328 :                         ttl = oil_if_has(c_oil, oif_vif_index);
    3779        3328 :                         if (ttl < 1)
    3780        3326 :                                 continue;
    3781             : 
    3782             :                         /* do not display muted OIFs */
    3783           2 :                         if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_MUTE)
    3784           0 :                                 continue;
    3785             : 
    3786           2 :                         if (*oil_parent(c_oil) == oif_vif_index &&
    3787           0 :                             !pim_mroute_allow_iif_in_oil(c_oil, oif_vif_index))
    3788           0 :                                 continue;
    3789             : 
    3790           2 :                         ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
    3791           2 :                         found_oif = 1;
    3792             : 
    3793           2 :                         if (ifp_out)
    3794           2 :                                 strlcpy(out_ifname, ifp_out->name,
    3795             :                                         sizeof(out_ifname));
    3796             :                         else
    3797           0 :                                 strlcpy(out_ifname, "<oif?>",
    3798             :                                         sizeof(out_ifname));
    3799             : 
    3800           2 :                         if (json) {
    3801           2 :                                 json_ifp_out = json_object_new_object();
    3802           2 :                                 json_object_string_add(json_ifp_out, "source",
    3803             :                                                        src_str);
    3804           2 :                                 json_object_string_add(json_ifp_out, "group",
    3805             :                                                        grp_str);
    3806             : 
    3807           2 :                                 if (c_oil->oif_flags[oif_vif_index] &
    3808             :                                     PIM_OIF_FLAG_PROTO_PIM)
    3809           2 :                                         json_object_boolean_true_add(
    3810             :                                                 json_ifp_out, "protocolPim");
    3811             : 
    3812           2 :                                 if (c_oil->oif_flags[oif_vif_index] &
    3813             :                                     PIM_OIF_FLAG_PROTO_GM)
    3814             : #if PIM_IPV == 4
    3815           0 :                                         json_object_boolean_true_add(
    3816             :                                                 json_ifp_out, "protocolIgmp");
    3817             : #else
    3818           0 :                                         json_object_boolean_true_add(
    3819             :                                                 json_ifp_out, "protocolMld");
    3820             : #endif
    3821             : 
    3822           2 :                                 if (c_oil->oif_flags[oif_vif_index] &
    3823             :                                     PIM_OIF_FLAG_PROTO_VXLAN)
    3824           0 :                                         json_object_boolean_true_add(
    3825             :                                                 json_ifp_out, "protocolVxlan");
    3826             : 
    3827           2 :                                 if (c_oil->oif_flags[oif_vif_index] &
    3828             :                                     PIM_OIF_FLAG_PROTO_STAR)
    3829           0 :                                         json_object_boolean_true_add(
    3830             :                                                 json_ifp_out,
    3831             :                                                 "protocolInherited");
    3832             : 
    3833           2 :                                 json_object_string_add(json_ifp_out,
    3834             :                                                        "inboundInterface",
    3835             :                                                        in_ifname);
    3836           2 :                                 json_object_int_add(json_ifp_out, "iVifI",
    3837           2 :                                                     *oil_parent(c_oil));
    3838           2 :                                 json_object_string_add(json_ifp_out,
    3839             :                                                        "outboundInterface",
    3840             :                                                        out_ifname);
    3841           2 :                                 json_object_int_add(json_ifp_out, "oVifI",
    3842             :                                                     oif_vif_index);
    3843           2 :                                 json_object_int_add(json_ifp_out, "ttl", ttl);
    3844           2 :                                 json_object_string_add(json_ifp_out, "upTime",
    3845             :                                                        mroute_uptime);
    3846           2 :                                 json_object_string_add(json_source, "flags",
    3847             :                                                        state_str);
    3848           2 :                                 if (!json_oil) {
    3849           2 :                                         json_oil = json_object_new_object();
    3850           2 :                                         json_object_object_add(json_source,
    3851             :                                                                "oil", json_oil);
    3852             :                                 }
    3853           2 :                                 json_object_object_add(json_oil, out_ifname,
    3854             :                                                        json_ifp_out);
    3855             :                         } else {
    3856           0 :                                 proto[0] = '\0';
    3857           0 :                                 if (c_oil->oif_flags[oif_vif_index] &
    3858             :                                     PIM_OIF_FLAG_PROTO_PIM) {
    3859           0 :                                         strlcpy(proto, "PIM", sizeof(proto));
    3860             :                                 }
    3861             : 
    3862           0 :                                 if (c_oil->oif_flags[oif_vif_index] &
    3863             :                                     PIM_OIF_FLAG_PROTO_GM) {
    3864             : #if PIM_IPV == 4
    3865           0 :                                         strlcpy(proto, "IGMP", sizeof(proto));
    3866             : #else
    3867           0 :                                         strlcpy(proto, "MLD", sizeof(proto));
    3868             : #endif
    3869             :                                 }
    3870             : 
    3871           0 :                                 if (c_oil->oif_flags[oif_vif_index] &
    3872             :                                     PIM_OIF_FLAG_PROTO_VXLAN) {
    3873           0 :                                         strlcpy(proto, "VxLAN", sizeof(proto));
    3874             :                                 }
    3875             : 
    3876           0 :                                 if (c_oil->oif_flags[oif_vif_index] &
    3877             :                                     PIM_OIF_FLAG_PROTO_STAR) {
    3878           0 :                                         strlcpy(proto, "STAR", sizeof(proto));
    3879             :                                 }
    3880             : 
    3881           0 :                                 ttable_add_row(tt, "%s|%s|%s|%s|%s|%s|%d|%s",
    3882             :                                                src_str, grp_str, state_str,
    3883             :                                                proto, in_ifname, out_ifname,
    3884             :                                                ttl, mroute_uptime);
    3885             : 
    3886           0 :                                 if (first) {
    3887           0 :                                         src_str[0] = '\0';
    3888           0 :                                         grp_str[0] = '\0';
    3889           0 :                                         in_ifname[0] = '\0';
    3890           0 :                                         state_str[0] = '\0';
    3891           0 :                                         mroute_uptime[0] = '\0';
    3892           0 :                                         first = 0;
    3893             :                                 }
    3894             :                         }
    3895             :                 }
    3896             : 
    3897          13 :                 if (!json && !found_oif) {
    3898           0 :                         ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
    3899             :                                        oil_origin(c_oil), oil_mcastgrp(c_oil),
    3900             :                                        state_str, "none", in_ifname, "none", 0,
    3901             :                                        "--:--:--");
    3902             :                 }
    3903             :         }
    3904             : 
    3905             :         /* Print list of static routes */
    3906          28 :         for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
    3907           0 :                 first = 1;
    3908             : 
    3909           0 :                 if (!s_route->c_oil.installed)
    3910           0 :                         continue;
    3911             : 
    3912           0 :                 snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &s_route->group);
    3913           0 :                 snprintfrr(src_str, sizeof(src_str), "%pPAs", &s_route->source);
    3914           0 :                 ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
    3915           0 :                 found_oif = 0;
    3916             : 
    3917           0 :                 if (ifp_in)
    3918           0 :                         strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
    3919             :                 else
    3920           0 :                         strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
    3921             : 
    3922           0 :                 if (json) {
    3923             : 
    3924             :                         /* Find the group, create it if it doesn't exist */
    3925           0 :                         json_object_object_get_ex(json, grp_str, &json_group);
    3926             : 
    3927           0 :                         if (!json_group) {
    3928           0 :                                 json_group = json_object_new_object();
    3929           0 :                                 json_object_object_add(json, grp_str,
    3930             :                                                        json_group);
    3931             :                         }
    3932             : 
    3933             :                         /* Find the source nested under the group, create it if
    3934             :                          * it doesn't exist
    3935             :                          */
    3936           0 :                         json_object_object_get_ex(json_group, src_str,
    3937             :                                                   &json_source);
    3938             : 
    3939           0 :                         if (!json_source) {
    3940           0 :                                 json_source = json_object_new_object();
    3941           0 :                                 json_object_object_add(json_group, src_str,
    3942             :                                                        json_source);
    3943             :                         }
    3944             : 
    3945           0 :                         json_object_string_add(json_source, "iif", in_ifname);
    3946           0 :                         json_oil = NULL;
    3947             :                 } else {
    3948           0 :                         strlcpy(proto, "STATIC", sizeof(proto));
    3949             :                 }
    3950             : 
    3951           0 :                 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
    3952           0 :                      ++oif_vif_index) {
    3953           0 :                         struct interface *ifp_out;
    3954           0 :                         char oif_uptime[10];
    3955           0 :                         int ttl;
    3956             : 
    3957           0 :                         ttl = s_route->oif_ttls[oif_vif_index];
    3958           0 :                         if (ttl < 1)
    3959           0 :                                 continue;
    3960             : 
    3961           0 :                         ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
    3962           0 :                         pim_time_uptime(
    3963             :                                 oif_uptime, sizeof(oif_uptime),
    3964             :                                 now - s_route->c_oil
    3965           0 :                                                 .oif_creation[oif_vif_index]);
    3966           0 :                         found_oif = 1;
    3967             : 
    3968           0 :                         if (ifp_out)
    3969           0 :                                 strlcpy(out_ifname, ifp_out->name,
    3970             :                                         sizeof(out_ifname));
    3971             :                         else
    3972           0 :                                 strlcpy(out_ifname, "<oif?>",
    3973             :                                         sizeof(out_ifname));
    3974             : 
    3975           0 :                         if (json) {
    3976           0 :                                 json_ifp_out = json_object_new_object();
    3977           0 :                                 json_object_string_add(json_ifp_out, "source",
    3978             :                                                        src_str);
    3979           0 :                                 json_object_string_add(json_ifp_out, "group",
    3980             :                                                        grp_str);
    3981           0 :                                 json_object_boolean_true_add(json_ifp_out,
    3982             :                                                              "protocolStatic");
    3983           0 :                                 json_object_string_add(json_ifp_out,
    3984             :                                                        "inboundInterface",
    3985             :                                                        in_ifname);
    3986           0 :                                 json_object_int_add(
    3987             :                                         json_ifp_out, "iVifI",
    3988           0 :                                         *oil_parent(&s_route->c_oil));
    3989           0 :                                 json_object_string_add(json_ifp_out,
    3990             :                                                        "outboundInterface",
    3991             :                                                        out_ifname);
    3992           0 :                                 json_object_int_add(json_ifp_out, "oVifI",
    3993             :                                                     oif_vif_index);
    3994           0 :                                 json_object_int_add(json_ifp_out, "ttl", ttl);
    3995           0 :                                 json_object_string_add(json_ifp_out, "upTime",
    3996             :                                                        oif_uptime);
    3997           0 :                                 if (!json_oil) {
    3998           0 :                                         json_oil = json_object_new_object();
    3999           0 :                                         json_object_object_add(json_source,
    4000             :                                                                "oil", json_oil);
    4001             :                                 }
    4002           0 :                                 json_object_object_add(json_oil, out_ifname,
    4003             :                                                        json_ifp_out);
    4004             :                         } else {
    4005           0 :                                 ttable_add_row(
    4006             :                                         tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
    4007             :                                         &s_route->source, &s_route->group, "-",
    4008             :                                         proto, in_ifname, out_ifname, ttl,
    4009             :                                         oif_uptime);
    4010           0 :                                 if (first && !fill) {
    4011           0 :                                         src_str[0] = '\0';
    4012           0 :                                         grp_str[0] = '\0';
    4013           0 :                                         in_ifname[0] = '\0';
    4014           0 :                                         first = 0;
    4015             :                                 }
    4016             :                         }
    4017             :                 }
    4018             : 
    4019           0 :                 if (!json && !found_oif) {
    4020           0 :                         ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
    4021             :                                        &s_route->source, &s_route->group, "-",
    4022             :                                        proto, in_ifname, "none", 0, "--:--:--");
    4023             :                 }
    4024             :         }
    4025             :         /* Dump the generated table. */
    4026          14 :         if (!json) {
    4027           0 :                 table = ttable_dump(tt, "\n");
    4028           0 :                 vty_out(vty, "%s\n", table);
    4029           0 :                 XFREE(MTYPE_TMP, table);
    4030           0 :                 ttable_del(tt);
    4031             :         }
    4032          14 : }
    4033             : 
    4034           0 : static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
    4035             :                                               json_object *json,
    4036             :                                               struct ttable *tt)
    4037             : {
    4038           0 :         json_object *json_group = NULL;
    4039           0 :         json_object *json_source = NULL;
    4040             : 
    4041           0 :         if (!c_oil->installed)
    4042           0 :                 return;
    4043             : 
    4044           0 :         pim_mroute_update_counters(c_oil);
    4045             : 
    4046           0 :         if (json) {
    4047           0 :                 char group_str[PIM_ADDRSTRLEN];
    4048           0 :                 char source_str[PIM_ADDRSTRLEN];
    4049             : 
    4050           0 :                 snprintfrr(group_str, sizeof(group_str), "%pPAs",
    4051             :                            oil_mcastgrp(c_oil));
    4052           0 :                 snprintfrr(source_str, sizeof(source_str), "%pPAs",
    4053             :                            oil_origin(c_oil));
    4054             : 
    4055           0 :                 json_object_object_get_ex(json, group_str, &json_group);
    4056             : 
    4057           0 :                 if (!json_group) {
    4058           0 :                         json_group = json_object_new_object();
    4059           0 :                         json_object_object_add(json, group_str, json_group);
    4060             :                 }
    4061             : 
    4062           0 :                 json_source = json_object_new_object();
    4063           0 :                 json_object_object_add(json_group, source_str, json_source);
    4064           0 :                 json_object_int_add(json_source, "lastUsed",
    4065           0 :                                     c_oil->cc.lastused / 100);
    4066           0 :                 json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
    4067           0 :                 json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
    4068           0 :                 json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
    4069             : 
    4070             :         } else {
    4071           0 :                 ttable_add_row(tt, "%pPAs|%pPAs|%llu|%ld|%ld|%ld",
    4072             :                                oil_origin(c_oil), oil_mcastgrp(c_oil),
    4073           0 :                                c_oil->cc.lastused / 100,
    4074           0 :                                c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
    4075           0 :                                c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
    4076           0 :                                c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
    4077             :         }
    4078             : }
    4079             : 
    4080           0 : void show_mroute_count(struct pim_instance *pim, struct vty *vty,
    4081             :                        json_object *json)
    4082             : {
    4083           0 :         struct listnode *node;
    4084           0 :         struct channel_oil *c_oil;
    4085           0 :         struct static_route *sr;
    4086           0 :         struct ttable *tt = NULL;
    4087           0 :         char *table = NULL;
    4088             : 
    4089           0 :         if (!json) {
    4090           0 :                 vty_out(vty, "\n");
    4091             : 
    4092             :                 /* Prepare table. */
    4093           0 :                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    4094           0 :                 ttable_add_row(tt,
    4095             :                                "Source|Group|LastUsed|Packets|Bytes|WrongIf");
    4096           0 :                 tt->style.cell.rpad = 2;
    4097           0 :                 tt->style.corner = '+';
    4098           0 :                 ttable_restyle(tt);
    4099             :         }
    4100             : 
    4101             :         /* Print PIM and IGMP route counts */
    4102           0 :         frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
    4103           0 :                 show_mroute_count_per_channel_oil(c_oil, json, tt);
    4104             : 
    4105           0 :         for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
    4106           0 :                 show_mroute_count_per_channel_oil(&sr->c_oil, json, tt);
    4107             : 
    4108             :         /* Dump the generated table. */
    4109           0 :         if (!json) {
    4110           0 :                 table = ttable_dump(tt, "\n");
    4111           0 :                 vty_out(vty, "%s\n", table);
    4112           0 :                 XFREE(MTYPE_TMP, table);
    4113           0 :                 ttable_del(tt);
    4114             :         }
    4115           0 : }
    4116             : 
    4117           0 : void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
    4118             :                          json_object *json)
    4119             : {
    4120           0 :         struct listnode *node;
    4121           0 :         struct channel_oil *c_oil;
    4122           0 :         struct static_route *s_route;
    4123           0 :         uint32_t starg_sw_mroute_cnt = 0;
    4124           0 :         uint32_t sg_sw_mroute_cnt = 0;
    4125           0 :         uint32_t starg_hw_mroute_cnt = 0;
    4126           0 :         uint32_t sg_hw_mroute_cnt = 0;
    4127           0 :         json_object *json_starg = NULL;
    4128           0 :         json_object *json_sg = NULL;
    4129             : 
    4130           0 :         if (!json)
    4131           0 :                 vty_out(vty, "Mroute Type    Installed/Total\n");
    4132             : 
    4133           0 :         frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
    4134           0 :                 if (!c_oil->installed) {
    4135           0 :                         if (pim_addr_is_any(*oil_origin(c_oil)))
    4136           0 :                                 starg_sw_mroute_cnt++;
    4137             :                         else
    4138           0 :                                 sg_sw_mroute_cnt++;
    4139             :                 } else {
    4140           0 :                         if (pim_addr_is_any(*oil_origin(c_oil)))
    4141           0 :                                 starg_hw_mroute_cnt++;
    4142             :                         else
    4143           0 :                                 sg_hw_mroute_cnt++;
    4144             :                 }
    4145             :         }
    4146             : 
    4147           0 :         for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
    4148           0 :                 if (!s_route->c_oil.installed) {
    4149           0 :                         if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
    4150           0 :                                 starg_sw_mroute_cnt++;
    4151             :                         else
    4152           0 :                                 sg_sw_mroute_cnt++;
    4153             :                 } else {
    4154           0 :                         if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
    4155           0 :                                 starg_hw_mroute_cnt++;
    4156             :                         else
    4157           0 :                                 sg_hw_mroute_cnt++;
    4158             :                 }
    4159             :         }
    4160             : 
    4161           0 :         if (!json) {
    4162           0 :                 vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
    4163             :                         starg_sw_mroute_cnt + starg_hw_mroute_cnt);
    4164           0 :                 vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
    4165             :                         sg_sw_mroute_cnt + sg_hw_mroute_cnt);
    4166           0 :                 vty_out(vty, "------\n");
    4167           0 :                 vty_out(vty, "%-20s %u/%u\n", "Total",
    4168             :                         (starg_hw_mroute_cnt + sg_hw_mroute_cnt),
    4169           0 :                         (starg_sw_mroute_cnt + starg_hw_mroute_cnt +
    4170             :                          sg_sw_mroute_cnt + sg_hw_mroute_cnt));
    4171             :         } else {
    4172             :                 /* (*,G) route details */
    4173           0 :                 json_starg = json_object_new_object();
    4174           0 :                 json_object_object_add(json, "wildcardGroup", json_starg);
    4175             : 
    4176           0 :                 json_object_int_add(json_starg, "installed",
    4177             :                                     starg_hw_mroute_cnt);
    4178           0 :                 json_object_int_add(json_starg, "total",
    4179           0 :                                     starg_sw_mroute_cnt + starg_hw_mroute_cnt);
    4180             : 
    4181             :                 /* (S, G) route details */
    4182           0 :                 json_sg = json_object_new_object();
    4183           0 :                 json_object_object_add(json, "sourceGroup", json_sg);
    4184             : 
    4185           0 :                 json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
    4186           0 :                 json_object_int_add(json_sg, "total",
    4187           0 :                                     sg_sw_mroute_cnt + sg_hw_mroute_cnt);
    4188             : 
    4189           0 :                 json_object_int_add(json, "totalNumOfInstalledMroutes",
    4190           0 :                                     starg_hw_mroute_cnt + sg_hw_mroute_cnt);
    4191           0 :                 json_object_int_add(json, "totalNumOfMroutes",
    4192           0 :                                     starg_sw_mroute_cnt + starg_hw_mroute_cnt +
    4193           0 :                                             sg_sw_mroute_cnt +
    4194             :                                             sg_hw_mroute_cnt);
    4195             :         }
    4196           0 : }
    4197             : 
    4198           0 : int clear_ip_mroute_count_command(struct vty *vty, const char *name)
    4199             : {
    4200           0 :         struct listnode *node;
    4201           0 :         struct channel_oil *c_oil;
    4202           0 :         struct static_route *sr;
    4203           0 :         struct vrf *v = pim_cmd_lookup(vty, name);
    4204           0 :         struct pim_instance *pim;
    4205             : 
    4206           0 :         if (!v)
    4207             :                 return CMD_WARNING;
    4208             : 
    4209           0 :         pim = v->info;
    4210           0 :         frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
    4211           0 :                 if (!c_oil->installed)
    4212           0 :                         continue;
    4213             : 
    4214           0 :                 pim_mroute_update_counters(c_oil);
    4215           0 :                 c_oil->cc.origpktcnt = c_oil->cc.pktcnt;
    4216           0 :                 c_oil->cc.origbytecnt = c_oil->cc.bytecnt;
    4217           0 :                 c_oil->cc.origwrong_if = c_oil->cc.wrong_if;
    4218             :         }
    4219             : 
    4220           0 :         for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
    4221           0 :                 if (!sr->c_oil.installed)
    4222           0 :                         continue;
    4223             : 
    4224           0 :                 pim_mroute_update_counters(&sr->c_oil);
    4225             : 
    4226           0 :                 sr->c_oil.cc.origpktcnt = sr->c_oil.cc.pktcnt;
    4227           0 :                 sr->c_oil.cc.origbytecnt = sr->c_oil.cc.bytecnt;
    4228           0 :                 sr->c_oil.cc.origwrong_if = sr->c_oil.cc.wrong_if;
    4229             :         }
    4230             :         return CMD_SUCCESS;
    4231             : }
    4232             : 
    4233           0 : struct vrf *pim_cmd_lookup(struct vty *vty, const char *name)
    4234             : {
    4235           0 :         struct vrf *vrf;
    4236             : 
    4237           0 :         if (name)
    4238           0 :                 vrf = vrf_lookup_by_name(name);
    4239             :         else
    4240           0 :                 vrf = vrf_lookup_by_id(VRF_DEFAULT);
    4241             : 
    4242           0 :         if (!vrf)
    4243           0 :                 vty_out(vty, "Specified VRF: %s does not exist\n", name);
    4244             : 
    4245           0 :         return vrf;
    4246             : }
    4247             : 
    4248           0 : void clear_mroute(struct pim_instance *pim)
    4249             : {
    4250           0 :         struct pim_upstream *up;
    4251           0 :         struct interface *ifp;
    4252             : 
    4253             :         /* scan interfaces */
    4254           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    4255           0 :                 struct pim_interface *pim_ifp = ifp->info;
    4256           0 :                 struct pim_ifchannel *ch;
    4257             : 
    4258           0 :                 if (!pim_ifp)
    4259           0 :                         continue;
    4260             : 
    4261             :                 /* deleting all ifchannels */
    4262           0 :                 while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
    4263           0 :                         ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
    4264             : 
    4265           0 :                         pim_ifchannel_delete(ch);
    4266             :                 }
    4267             : 
    4268             : #if PIM_IPV == 4
    4269             :                 /* clean up all igmp groups */
    4270           0 :                 struct gm_group *grp;
    4271             : 
    4272           0 :                 if (pim_ifp->gm_group_list) {
    4273           0 :                         while (pim_ifp->gm_group_list->count) {
    4274           0 :                                 grp = listnode_head(pim_ifp->gm_group_list);
    4275           0 :                                 igmp_group_delete(grp);
    4276             :                         }
    4277             :                 }
    4278             : #else
    4279           0 :                 struct gm_if *gm_ifp;
    4280             : 
    4281           0 :                 gm_ifp = pim_ifp->mld;
    4282           0 :                 if (gm_ifp)
    4283           0 :                         gm_group_delete(gm_ifp);
    4284             : #endif
    4285             :         }
    4286             : 
    4287             :         /* clean up all upstreams*/
    4288           0 :         while ((up = rb_pim_upstream_first(&pim->upstream_head)))
    4289           0 :                 pim_upstream_del(pim, up, __func__);
    4290           0 : }
    4291             : 
    4292           0 : void clear_pim_statistics(struct pim_instance *pim)
    4293             : {
    4294           0 :         struct interface *ifp;
    4295             : 
    4296           0 :         pim->bsm_rcvd = 0;
    4297           0 :         pim->bsm_sent = 0;
    4298           0 :         pim->bsm_dropped = 0;
    4299             : 
    4300             :         /* scan interfaces */
    4301           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    4302           0 :                 struct pim_interface *pim_ifp = ifp->info;
    4303             : 
    4304           0 :                 if (!pim_ifp)
    4305           0 :                         continue;
    4306             : 
    4307           0 :                 pim_ifp->pim_ifstat_bsm_cfg_miss = 0;
    4308           0 :                 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0;
    4309           0 :                 pim_ifp->pim_ifstat_bsm_invalid_sz = 0;
    4310             :         }
    4311           0 : }
    4312             : 
    4313           0 : int clear_pim_interface_traffic(const char *vrf, struct vty *vty)
    4314             : {
    4315           0 :         struct interface *ifp = NULL;
    4316           0 :         struct pim_interface *pim_ifp = NULL;
    4317             : 
    4318           0 :         struct vrf *v = pim_cmd_lookup(vty, vrf);
    4319             : 
    4320           0 :         if (!v)
    4321             :                 return CMD_WARNING;
    4322             : 
    4323           0 :         FOR_ALL_INTERFACES (v, ifp) {
    4324           0 :                 pim_ifp = ifp->info;
    4325             : 
    4326           0 :                 if (!pim_ifp)
    4327           0 :                         continue;
    4328             : 
    4329           0 :                 pim_ifp->pim_ifstat_hello_recv = 0;
    4330           0 :                 pim_ifp->pim_ifstat_hello_sent = 0;
    4331           0 :                 pim_ifp->pim_ifstat_join_recv = 0;
    4332           0 :                 pim_ifp->pim_ifstat_join_send = 0;
    4333           0 :                 pim_ifp->pim_ifstat_prune_recv = 0;
    4334           0 :                 pim_ifp->pim_ifstat_prune_send = 0;
    4335           0 :                 pim_ifp->pim_ifstat_reg_recv = 0;
    4336           0 :                 pim_ifp->pim_ifstat_reg_send = 0;
    4337           0 :                 pim_ifp->pim_ifstat_reg_stop_recv = 0;
    4338           0 :                 pim_ifp->pim_ifstat_reg_stop_send = 0;
    4339           0 :                 pim_ifp->pim_ifstat_assert_recv = 0;
    4340           0 :                 pim_ifp->pim_ifstat_assert_send = 0;
    4341           0 :                 pim_ifp->pim_ifstat_bsm_rx = 0;
    4342           0 :                 pim_ifp->pim_ifstat_bsm_tx = 0;
    4343             : #if PIM_IPV == 4
    4344           0 :                 pim_ifp->igmp_ifstat_joins_sent = 0;
    4345           0 :                 pim_ifp->igmp_ifstat_joins_failed = 0;
    4346           0 :                 pim_ifp->igmp_peak_group_count = 0;
    4347             : #endif
    4348             :         }
    4349             : 
    4350             :         return CMD_SUCCESS;
    4351             : }
    4352             : 
    4353           0 : int pim_debug_pim_cmd(void)
    4354             : {
    4355           0 :         PIM_DO_DEBUG_PIM_EVENTS;
    4356           0 :         PIM_DO_DEBUG_PIM_PACKETS;
    4357           0 :         PIM_DO_DEBUG_PIM_TRACE;
    4358           0 :         PIM_DO_DEBUG_MSDP_EVENTS;
    4359           0 :         PIM_DO_DEBUG_MSDP_PACKETS;
    4360           0 :         PIM_DO_DEBUG_BSM;
    4361           0 :         PIM_DO_DEBUG_VXLAN;
    4362           0 :         return CMD_SUCCESS;
    4363             : }
    4364             : 
    4365           0 : int pim_no_debug_pim_cmd(void)
    4366             : {
    4367           0 :         PIM_DONT_DEBUG_PIM_EVENTS;
    4368           0 :         PIM_DONT_DEBUG_PIM_PACKETS;
    4369           0 :         PIM_DONT_DEBUG_PIM_TRACE;
    4370           0 :         PIM_DONT_DEBUG_MSDP_EVENTS;
    4371           0 :         PIM_DONT_DEBUG_MSDP_PACKETS;
    4372             : 
    4373           0 :         PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
    4374           0 :         PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
    4375           0 :         PIM_DONT_DEBUG_BSM;
    4376           0 :         PIM_DONT_DEBUG_VXLAN;
    4377           0 :         return CMD_SUCCESS;
    4378             : }
    4379             : 
    4380           0 : int pim_debug_pim_packets_cmd(const char *hello, const char *joins,
    4381             :                               const char *registers, struct vty *vty)
    4382             : {
    4383           0 :         if (hello) {
    4384           0 :                 PIM_DO_DEBUG_PIM_HELLO;
    4385           0 :                 vty_out(vty, "PIM Hello debugging is on\n");
    4386           0 :         } else if (joins) {
    4387           0 :                 PIM_DO_DEBUG_PIM_J_P;
    4388           0 :                 vty_out(vty, "PIM Join/Prune debugging is on\n");
    4389           0 :         } else if (registers) {
    4390           0 :                 PIM_DO_DEBUG_PIM_REG;
    4391           0 :                 vty_out(vty, "PIM Register debugging is on\n");
    4392             :         } else {
    4393           0 :                 PIM_DO_DEBUG_PIM_PACKETS;
    4394           0 :                 vty_out(vty, "PIM Packet debugging is on\n");
    4395             :         }
    4396           0 :         return CMD_SUCCESS;
    4397             : }
    4398             : 
    4399           0 : int pim_no_debug_pim_packets_cmd(const char *hello, const char *joins,
    4400             :                                  const char *registers, struct vty *vty)
    4401             : {
    4402           0 :         if (hello) {
    4403           0 :                 PIM_DONT_DEBUG_PIM_HELLO;
    4404           0 :                 vty_out(vty, "PIM Hello debugging is off\n");
    4405           0 :         } else if (joins) {
    4406           0 :                 PIM_DONT_DEBUG_PIM_J_P;
    4407           0 :                 vty_out(vty, "PIM Join/Prune debugging is off\n");
    4408           0 :         } else if (registers) {
    4409           0 :                 PIM_DONT_DEBUG_PIM_REG;
    4410           0 :                 vty_out(vty, "PIM Register debugging is off\n");
    4411             :         } else {
    4412           0 :                 PIM_DONT_DEBUG_PIM_PACKETS;
    4413           0 :                 vty_out(vty, "PIM Packet debugging is off\n");
    4414             :         }
    4415             : 
    4416           0 :         return CMD_SUCCESS;
    4417             : }
    4418             : 
    4419           0 : int pim_show_rpf_helper(const char *vrf, struct vty *vty, bool json)
    4420             : {
    4421           0 :         struct pim_instance *pim;
    4422           0 :         struct vrf *v;
    4423           0 :         json_object *json_parent = NULL;
    4424             : 
    4425           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4426             : 
    4427           0 :         if (!v)
    4428             :                 return CMD_WARNING;
    4429             : 
    4430           0 :         pim = v->info;
    4431             : 
    4432           0 :         if (!pim) {
    4433           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4434           0 :                 return CMD_WARNING;
    4435             :         }
    4436             : 
    4437           0 :         if (json)
    4438           0 :                 json_parent = json_object_new_object();
    4439             : 
    4440           0 :         pim_show_rpf(pim, vty, json_parent);
    4441             : 
    4442           0 :         if (json)
    4443           0 :                 vty_json(vty, json_parent);
    4444             : 
    4445             :         return CMD_SUCCESS;
    4446             : }
    4447             : 
    4448           0 : int pim_show_rpf_vrf_all_helper(struct vty *vty, bool json)
    4449             : {
    4450           0 :         struct vrf *vrf;
    4451           0 :         json_object *json_parent = NULL;
    4452           0 :         json_object *json_vrf = NULL;
    4453             : 
    4454           0 :         if (json)
    4455           0 :                 json_parent = json_object_new_object();
    4456             : 
    4457           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    4458           0 :                 if (!json)
    4459           0 :                         vty_out(vty, "VRF: %s\n", vrf->name);
    4460             :                 else
    4461           0 :                         json_vrf = json_object_new_object();
    4462           0 :                 pim_show_rpf(vrf->info, vty, json_vrf);
    4463           0 :                 if (json)
    4464           0 :                         json_object_object_add(json_parent, vrf->name,
    4465             :                                                json_vrf);
    4466             :         }
    4467           0 :         if (json)
    4468           0 :                 vty_json(vty, json_parent);
    4469             : 
    4470           0 :         return CMD_SUCCESS;
    4471             : }
    4472             : 
    4473           4 : int pim_show_rp_helper(const char *vrf, struct vty *vty, const char *group_str,
    4474             :                        const struct prefix *group, bool json)
    4475             : {
    4476           4 :         struct pim_instance *pim;
    4477           4 :         struct vrf *v;
    4478           4 :         json_object *json_parent = NULL;
    4479           4 :         struct prefix *range = NULL;
    4480             : 
    4481           4 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4482             : 
    4483           4 :         if (!v)
    4484             :                 return CMD_WARNING;
    4485             : 
    4486           4 :         pim = v->info;
    4487             : 
    4488           4 :         if (!pim) {
    4489           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4490           0 :                 return CMD_WARNING;
    4491             :         }
    4492             : 
    4493           4 :         if (group_str) {
    4494           0 :                 range = prefix_new();
    4495           0 :                 prefix_copy(range, group);
    4496           0 :                 apply_mask(range);
    4497             :         }
    4498             : 
    4499           4 :         if (json)
    4500           1 :                 json_parent = json_object_new_object();
    4501             : 
    4502           4 :         pim_rp_show_information(pim, range, vty, json_parent);
    4503             : 
    4504           4 :         if (json)
    4505           1 :                 vty_json(vty, json_parent);
    4506             : 
    4507           4 :         prefix_free(&range);
    4508             : 
    4509           4 :         return CMD_SUCCESS;
    4510             : }
    4511             : 
    4512           0 : int pim_show_rp_vrf_all_helper(struct vty *vty, const char *group_str,
    4513             :                                const struct prefix *group, bool json)
    4514             : {
    4515           0 :         struct vrf *vrf;
    4516           0 :         json_object *json_parent = NULL;
    4517           0 :         json_object *json_vrf = NULL;
    4518           0 :         struct prefix *range = NULL;
    4519             : 
    4520           0 :         if (group_str) {
    4521           0 :                 range = prefix_new();
    4522           0 :                 prefix_copy(range, group);
    4523           0 :                 apply_mask(range);
    4524             :         }
    4525             : 
    4526           0 :         if (json)
    4527           0 :                 json_parent = json_object_new_object();
    4528             : 
    4529           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    4530           0 :                 if (!json)
    4531           0 :                         vty_out(vty, "VRF: %s\n", vrf->name);
    4532             :                 else
    4533           0 :                         json_vrf = json_object_new_object();
    4534           0 :                 pim_rp_show_information(vrf->info, range, vty, json_vrf);
    4535           0 :                 if (json)
    4536           0 :                         json_object_object_add(json_parent, vrf->name,
    4537             :                                                json_vrf);
    4538             :         }
    4539           0 :         if (json)
    4540           0 :                 vty_json(vty, json_parent);
    4541             : 
    4542           0 :         prefix_free(&range);
    4543             : 
    4544           0 :         return CMD_SUCCESS;
    4545             : }
    4546             : 
    4547           0 : int pim_show_secondary_helper(const char *vrf, struct vty *vty)
    4548             : {
    4549           0 :         struct pim_instance *pim;
    4550           0 :         struct vrf *v;
    4551             : 
    4552           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4553             : 
    4554           0 :         if (!v)
    4555             :                 return CMD_WARNING;
    4556             : 
    4557           0 :         pim = v->info;
    4558             : 
    4559           0 :         if (!pim) {
    4560           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4561           0 :                 return CMD_WARNING;
    4562             :         }
    4563             : 
    4564           0 :         pim_show_neighbors_secondary(pim, vty);
    4565             : 
    4566           0 :         return CMD_SUCCESS;
    4567             : }
    4568             : 
    4569           0 : int pim_show_statistics_helper(const char *vrf, struct vty *vty,
    4570             :                                const char *word, bool uj)
    4571             : {
    4572           0 :         struct pim_instance *pim;
    4573           0 :         struct vrf *v;
    4574             : 
    4575           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4576             : 
    4577           0 :         if (!v)
    4578             :                 return CMD_WARNING;
    4579             : 
    4580           0 :         pim = v->info;
    4581             : 
    4582           0 :         if (!pim) {
    4583           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4584           0 :                 return CMD_WARNING;
    4585             :         }
    4586             : 
    4587           0 :         if (word)
    4588           0 :                 pim_show_statistics(pim, vty, word, uj);
    4589             :         else
    4590           0 :                 pim_show_statistics(pim, vty, NULL, uj);
    4591             : 
    4592             :         return CMD_SUCCESS;
    4593             : }
    4594             : 
    4595           4 : int pim_show_upstream_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
    4596             :                              pim_addr g, bool json)
    4597             : {
    4598           4 :         pim_sgaddr sg = {0};
    4599           4 :         struct vrf *v;
    4600           4 :         struct pim_instance *pim;
    4601           4 :         json_object *json_parent = NULL;
    4602             : 
    4603           4 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4604             : 
    4605           4 :         if (!v) {
    4606           0 :                 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
    4607           0 :                 return CMD_WARNING;
    4608             :         }
    4609           4 :         pim = v->info;
    4610             : 
    4611           4 :         if (!pim) {
    4612           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4613           0 :                 return CMD_WARNING;
    4614             :         }
    4615             : 
    4616           4 :         if (json)
    4617           4 :                 json_parent = json_object_new_object();
    4618             : 
    4619           4 :         if (!pim_addr_is_any(s_or_g)) {
    4620           0 :                 if (!pim_addr_is_any(g)) {
    4621           0 :                         sg.src = s_or_g;
    4622           0 :                         sg.grp = g;
    4623             :                 } else
    4624           0 :                         sg.grp = s_or_g;
    4625             :         }
    4626             : 
    4627           4 :         pim_show_upstream(pim, vty, &sg, json_parent);
    4628             : 
    4629           4 :         if (json)
    4630           4 :                 vty_json(vty, json_parent);
    4631             : 
    4632             :         return CMD_SUCCESS;
    4633             : }
    4634             : 
    4635           0 : int pim_show_upstream_vrf_all_helper(struct vty *vty, bool json)
    4636             : {
    4637           0 :         pim_sgaddr sg = {0};
    4638           0 :         struct vrf *vrf;
    4639           0 :         json_object *json_parent = NULL;
    4640           0 :         json_object *json_vrf = NULL;
    4641             : 
    4642           0 :         if (json)
    4643           0 :                 json_parent = json_object_new_object();
    4644             : 
    4645           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    4646           0 :                 if (!json)
    4647           0 :                         vty_out(vty, "VRF: %s\n", vrf->name);
    4648             :                 else
    4649           0 :                         json_vrf = json_object_new_object();
    4650           0 :                 pim_show_upstream(vrf->info, vty, &sg, json_vrf);
    4651           0 :                 if (json)
    4652           0 :                         json_object_object_add(json_parent, vrf->name,
    4653             :                                                json_vrf);
    4654             :         }
    4655             : 
    4656           0 :         if (json)
    4657           0 :                 vty_json(vty, json_parent);
    4658             : 
    4659           0 :         return CMD_SUCCESS;
    4660             : }
    4661             : 
    4662           0 : int pim_show_upstream_join_desired_helper(const char *vrf, struct vty *vty,
    4663             :                                           bool uj)
    4664             : {
    4665           0 :         struct pim_instance *pim;
    4666           0 :         struct vrf *v;
    4667             : 
    4668           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4669             : 
    4670           0 :         if (!v)
    4671             :                 return CMD_WARNING;
    4672             : 
    4673           0 :         pim = v->info;
    4674             : 
    4675           0 :         if (!pim) {
    4676           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4677           0 :                 return CMD_WARNING;
    4678             :         }
    4679             : 
    4680           0 :         pim_show_join_desired(pim, vty, uj);
    4681             : 
    4682           0 :         return CMD_SUCCESS;
    4683             : }
    4684             : 
    4685           0 : int pim_show_upstream_rpf_helper(const char *vrf, struct vty *vty, bool uj)
    4686             : {
    4687           0 :         struct pim_instance *pim;
    4688           0 :         struct vrf *v;
    4689             : 
    4690           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4691             : 
    4692           0 :         if (!v)
    4693             :                 return CMD_WARNING;
    4694             : 
    4695           0 :         pim = v->info;
    4696             : 
    4697           0 :         if (!pim) {
    4698           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4699           0 :                 return CMD_WARNING;
    4700             :         }
    4701             : 
    4702           0 :         pim_show_upstream_rpf(pim, vty, uj);
    4703             : 
    4704           0 :         return CMD_SUCCESS;
    4705             : }
    4706             : 
    4707           0 : int pim_show_state_helper(const char *vrf, struct vty *vty,
    4708             :                           const char *s_or_g_str, const char *g_str, bool json)
    4709             : {
    4710           0 :         struct pim_instance *pim;
    4711           0 :         struct vrf *v;
    4712           0 :         json_object *json_parent = NULL;
    4713             : 
    4714           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4715             : 
    4716           0 :         if (!v)
    4717             :                 return CMD_WARNING;
    4718             : 
    4719           0 :         pim = v->info;
    4720             : 
    4721           0 :         if (!pim) {
    4722           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4723           0 :                 return CMD_WARNING;
    4724             :         }
    4725             : 
    4726           0 :         if (json)
    4727           0 :                 json_parent = json_object_new_object();
    4728             : 
    4729           0 :         pim_show_state(pim, vty, s_or_g_str, g_str, json_parent);
    4730             : 
    4731           0 :         if (json)
    4732           0 :                 vty_json(vty, json_parent);
    4733             : 
    4734             :         return CMD_SUCCESS;
    4735             : }
    4736             : 
    4737           0 : int pim_show_state_vrf_all_helper(struct vty *vty, const char *s_or_g_str,
    4738             :                                   const char *g_str, bool json)
    4739             : {
    4740           0 :         struct vrf *vrf;
    4741           0 :         json_object *json_parent = NULL;
    4742           0 :         json_object *json_vrf = NULL;
    4743             : 
    4744           0 :         if (json)
    4745           0 :                 json_parent = json_object_new_object();
    4746             : 
    4747           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    4748           0 :                 if (!json)
    4749           0 :                         vty_out(vty, "VRF: %s\n", vrf->name);
    4750             :                 else
    4751           0 :                         json_vrf = json_object_new_object();
    4752           0 :                 pim_show_state(vrf->info, vty, s_or_g_str, g_str, json_vrf);
    4753           0 :                 if (json)
    4754           0 :                         json_object_object_add(json_parent, vrf->name,
    4755             :                                                json_vrf);
    4756             :         }
    4757           0 :         if (json)
    4758           0 :                 vty_json(vty, json_parent);
    4759             : 
    4760           0 :         return CMD_SUCCESS;
    4761             : }
    4762             : 
    4763           0 : int pim_show_multicast_helper(const char *vrf, struct vty *vty)
    4764             : {
    4765           0 :         struct vrf *v;
    4766           0 :         struct pim_instance *pim;
    4767             : 
    4768           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4769             : 
    4770           0 :         if (!v)
    4771             :                 return CMD_WARNING;
    4772             : 
    4773           0 :         pim = v->info;
    4774             : 
    4775           0 :         if (!pim) {
    4776           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4777           0 :                 return CMD_WARNING;
    4778             :         }
    4779             : 
    4780           0 :         pim_cmd_show_ip_multicast_helper(pim, vty);
    4781             : 
    4782           0 :         return CMD_SUCCESS;
    4783             : }
    4784             : 
    4785           0 : int pim_show_multicast_vrf_all_helper(struct vty *vty)
    4786             : {
    4787           0 :         struct vrf *vrf;
    4788             : 
    4789           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    4790           0 :                 vty_out(vty, "VRF: %s\n", vrf->name);
    4791           0 :                 pim_cmd_show_ip_multicast_helper(vrf->info, vty);
    4792             :         }
    4793             : 
    4794           0 :         return CMD_SUCCESS;
    4795             : }
    4796             : 
    4797           0 : int pim_show_multicast_count_helper(const char *vrf, struct vty *vty, bool json)
    4798             : {
    4799           0 :         struct pim_instance *pim;
    4800           0 :         struct vrf *v;
    4801           0 :         json_object *json_parent = NULL;
    4802             : 
    4803           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4804             : 
    4805           0 :         if (!v)
    4806             :                 return CMD_WARNING;
    4807             : 
    4808           0 :         pim = v->info;
    4809             : 
    4810           0 :         if (!pim) {
    4811           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4812           0 :                 return CMD_WARNING;
    4813             :         }
    4814             : 
    4815           0 :         if (json)
    4816           0 :                 json_parent = json_object_new_object();
    4817             : 
    4818           0 :         show_multicast_interfaces(pim, vty, json_parent);
    4819             : 
    4820           0 :         if (json)
    4821           0 :                 vty_json(vty, json_parent);
    4822             : 
    4823             :         return CMD_SUCCESS;
    4824             : }
    4825             : 
    4826           0 : int pim_show_multicast_count_vrf_all_helper(struct vty *vty, bool json)
    4827             : {
    4828           0 :         struct vrf *vrf;
    4829           0 :         json_object *json_parent = NULL;
    4830           0 :         json_object *json_vrf = NULL;
    4831             : 
    4832           0 :         if (json)
    4833           0 :                 json_parent = json_object_new_object();
    4834             : 
    4835           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    4836           0 :                 if (!json)
    4837           0 :                         vty_out(vty, "VRF: %s\n", vrf->name);
    4838             :                 else
    4839           0 :                         json_vrf = json_object_new_object();
    4840             : 
    4841           0 :                 show_multicast_interfaces(vrf->info, vty, json_vrf);
    4842           0 :                 if (json)
    4843           0 :                         json_object_object_add(json_parent, vrf->name,
    4844             :                                                json_vrf);
    4845             :         }
    4846           0 :         if (json)
    4847           0 :                 vty_json(vty, json_parent);
    4848             : 
    4849           0 :         return CMD_SUCCESS;
    4850             : }
    4851             : 
    4852          14 : int pim_show_mroute_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
    4853             :                            pim_addr g, bool fill, bool json)
    4854             : {
    4855          14 :         pim_sgaddr sg = {0};
    4856          14 :         struct pim_instance *pim;
    4857          14 :         struct vrf *v;
    4858          14 :         json_object *json_parent = NULL;
    4859             : 
    4860          14 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4861             : 
    4862          14 :         if (!v)
    4863             :                 return CMD_WARNING;
    4864             : 
    4865          14 :         pim = v->info;
    4866             : 
    4867          14 :         if (!pim) {
    4868           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4869           0 :                 return CMD_WARNING;
    4870             :         }
    4871             : 
    4872          14 :         if (json)
    4873          14 :                 json_parent = json_object_new_object();
    4874             : 
    4875          14 :         if (!pim_addr_is_any(s_or_g)) {
    4876           0 :                 if (!pim_addr_is_any(g)) {
    4877           0 :                         sg.src = s_or_g;
    4878           0 :                         sg.grp = g;
    4879             :                 } else
    4880           0 :                         sg.grp = s_or_g;
    4881             :         }
    4882             : 
    4883          14 :         show_mroute(pim, vty, &sg, fill, json_parent);
    4884             : 
    4885          14 :         if (json)
    4886          14 :                 vty_json(vty, json_parent);
    4887             : 
    4888             :         return CMD_SUCCESS;
    4889             : }
    4890             : 
    4891           0 : int pim_show_mroute_vrf_all_helper(struct vty *vty, bool fill, bool json)
    4892             : {
    4893           0 :         pim_sgaddr sg = {0};
    4894           0 :         struct vrf *vrf;
    4895           0 :         json_object *json_parent = NULL;
    4896           0 :         json_object *json_vrf = NULL;
    4897             : 
    4898           0 :         if (json)
    4899           0 :                 json_parent = json_object_new_object();
    4900             : 
    4901           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    4902           0 :                 if (!json)
    4903           0 :                         vty_out(vty, "VRF: %s\n", vrf->name);
    4904             :                 else
    4905           0 :                         json_vrf = json_object_new_object();
    4906           0 :                 show_mroute(vrf->info, vty, &sg, fill, json_vrf);
    4907           0 :                 if (json)
    4908           0 :                         json_object_object_add(json_parent, vrf->name,
    4909             :                                                json_vrf);
    4910             :         }
    4911           0 :         if (json)
    4912           0 :                 vty_json(vty, json_parent);
    4913             : 
    4914           0 :         return CMD_SUCCESS;
    4915             : }
    4916             : 
    4917           0 : int pim_show_mroute_count_helper(const char *vrf, struct vty *vty, bool json)
    4918             : {
    4919           0 :         struct pim_instance *pim;
    4920           0 :         struct vrf *v;
    4921           0 :         json_object *json_parent = NULL;
    4922             : 
    4923           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4924             : 
    4925           0 :         if (!v)
    4926             :                 return CMD_WARNING;
    4927             : 
    4928           0 :         pim = v->info;
    4929             : 
    4930           0 :         if (!pim) {
    4931           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4932           0 :                 return CMD_WARNING;
    4933             :         }
    4934             : 
    4935           0 :         if (json)
    4936           0 :                 json_parent = json_object_new_object();
    4937             : 
    4938           0 :         show_mroute_count(pim, vty, json_parent);
    4939             : 
    4940           0 :         if (json)
    4941           0 :                 vty_json(vty, json_parent);
    4942             : 
    4943             :         return CMD_SUCCESS;
    4944             : }
    4945             : 
    4946           0 : int pim_show_mroute_count_vrf_all_helper(struct vty *vty, bool json)
    4947             : {
    4948           0 :         struct vrf *vrf;
    4949           0 :         json_object *json_parent = NULL;
    4950           0 :         json_object *json_vrf = NULL;
    4951             : 
    4952           0 :         if (json)
    4953           0 :                 json_parent = json_object_new_object();
    4954             : 
    4955           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    4956           0 :                 if (!json)
    4957           0 :                         vty_out(vty, "VRF: %s\n", vrf->name);
    4958             :                 else
    4959           0 :                         json_vrf = json_object_new_object();
    4960             : 
    4961           0 :                 show_mroute_count(vrf->info, vty, json_vrf);
    4962             : 
    4963           0 :                 if (json)
    4964           0 :                         json_object_object_add(json_parent, vrf->name,
    4965             :                                                json_vrf);
    4966             :         }
    4967           0 :         if (json)
    4968           0 :                 vty_json(vty, json_parent);
    4969             : 
    4970           0 :         return CMD_SUCCESS;
    4971             : }
    4972             : 
    4973           0 : int pim_show_mroute_summary_helper(const char *vrf, struct vty *vty, bool json)
    4974             : {
    4975           0 :         struct pim_instance *pim;
    4976           0 :         struct vrf *v;
    4977           0 :         json_object *json_parent = NULL;
    4978             : 
    4979           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    4980             : 
    4981           0 :         if (!v)
    4982             :                 return CMD_WARNING;
    4983             : 
    4984           0 :         pim = v->info;
    4985             : 
    4986           0 :         if (!pim) {
    4987           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    4988           0 :                 return CMD_WARNING;
    4989             :         }
    4990             : 
    4991           0 :         if (json)
    4992           0 :                 json_parent = json_object_new_object();
    4993             : 
    4994           0 :         show_mroute_summary(pim, vty, json_parent);
    4995             : 
    4996           0 :         if (json)
    4997           0 :                 vty_json(vty, json_parent);
    4998             : 
    4999             :         return CMD_SUCCESS;
    5000             : }
    5001             : 
    5002           0 : int pim_show_mroute_summary_vrf_all_helper(struct vty *vty, bool json)
    5003             : {
    5004           0 :         struct vrf *vrf;
    5005           0 :         json_object *json_parent = NULL;
    5006           0 :         json_object *json_vrf = NULL;
    5007             : 
    5008           0 :         if (json)
    5009           0 :                 json_parent = json_object_new_object();
    5010             : 
    5011           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    5012           0 :                 if (!json)
    5013           0 :                         vty_out(vty, "VRF: %s\n", vrf->name);
    5014             :                 else
    5015           0 :                         json_vrf = json_object_new_object();
    5016             : 
    5017           0 :                 show_mroute_summary(vrf->info, vty, json_vrf);
    5018             : 
    5019           0 :                 if (json)
    5020           0 :                         json_object_object_add(json_parent, vrf->name,
    5021             :                                                json_vrf);
    5022             :         }
    5023             : 
    5024           0 :         if (json)
    5025           0 :                 vty_json(vty, json_parent);
    5026             : 
    5027           0 :         return CMD_SUCCESS;
    5028             : }
    5029             : 
    5030           0 : void pim_show_interface_traffic(struct pim_instance *pim, struct vty *vty,
    5031             :                                 bool uj)
    5032             : {
    5033           0 :         struct interface *ifp = NULL;
    5034           0 :         struct pim_interface *pim_ifp = NULL;
    5035           0 :         json_object *json = NULL;
    5036           0 :         json_object *json_row = NULL;
    5037             : 
    5038           0 :         if (uj)
    5039           0 :                 json = json_object_new_object();
    5040             :         else {
    5041           0 :                 vty_out(vty, "\n");
    5042           0 :                 vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
    5043             :                         "Interface", "       HELLO", "       JOIN",
    5044             :                         "      PRUNE", "   REGISTER", "REGISTER-STOP",
    5045             :                         "  ASSERT", "  BSM");
    5046           0 :                 vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
    5047             :                         "       Rx/Tx", "       Rx/Tx", "      Rx/Tx",
    5048             :                         "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "   Rx/Tx");
    5049           0 :                 vty_out(vty,
    5050             :                         "---------------------------------------------------------------------------------------------------------------\n");
    5051             :         }
    5052             : 
    5053           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    5054           0 :                 pim_ifp = ifp->info;
    5055             : 
    5056           0 :                 if (!pim_ifp)
    5057           0 :                         continue;
    5058             : 
    5059           0 :                 if (uj) {
    5060           0 :                         json_row = json_object_new_object();
    5061           0 :                         json_object_pim_ifp_add(json_row, ifp);
    5062           0 :                         json_object_int_add(json_row, "helloRx",
    5063           0 :                                             pim_ifp->pim_ifstat_hello_recv);
    5064           0 :                         json_object_int_add(json_row, "helloTx",
    5065           0 :                                             pim_ifp->pim_ifstat_hello_sent);
    5066           0 :                         json_object_int_add(json_row, "joinRx",
    5067           0 :                                             pim_ifp->pim_ifstat_join_recv);
    5068           0 :                         json_object_int_add(json_row, "joinTx",
    5069           0 :                                             pim_ifp->pim_ifstat_join_send);
    5070           0 :                         json_object_int_add(json_row, "pruneRx",
    5071           0 :                                             pim_ifp->pim_ifstat_prune_recv);
    5072           0 :                         json_object_int_add(json_row, "pruneTx",
    5073           0 :                                             pim_ifp->pim_ifstat_prune_send);
    5074           0 :                         json_object_int_add(json_row, "registerRx",
    5075           0 :                                             pim_ifp->pim_ifstat_reg_recv);
    5076           0 :                         json_object_int_add(json_row, "registerTx",
    5077           0 :                                             pim_ifp->pim_ifstat_reg_send);
    5078           0 :                         json_object_int_add(json_row, "registerStopRx",
    5079           0 :                                             pim_ifp->pim_ifstat_reg_stop_recv);
    5080           0 :                         json_object_int_add(json_row, "registerStopTx",
    5081           0 :                                             pim_ifp->pim_ifstat_reg_stop_send);
    5082           0 :                         json_object_int_add(json_row, "assertRx",
    5083           0 :                                             pim_ifp->pim_ifstat_assert_recv);
    5084           0 :                         json_object_int_add(json_row, "assertTx",
    5085           0 :                                             pim_ifp->pim_ifstat_assert_send);
    5086           0 :                         json_object_int_add(json_row, "bsmRx",
    5087           0 :                                             pim_ifp->pim_ifstat_bsm_rx);
    5088           0 :                         json_object_int_add(json_row, "bsmTx",
    5089           0 :                                             pim_ifp->pim_ifstat_bsm_tx);
    5090           0 :                         json_object_object_add(json, ifp->name, json_row);
    5091             :                 } else {
    5092           0 :                         vty_out(vty,
    5093             :                                 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
    5094             :                                 "/%-7" PRIu64 "\n",
    5095           0 :                                 ifp->name, pim_ifp->pim_ifstat_hello_recv,
    5096             :                                 pim_ifp->pim_ifstat_hello_sent,
    5097             :                                 pim_ifp->pim_ifstat_join_recv,
    5098             :                                 pim_ifp->pim_ifstat_join_send,
    5099             :                                 pim_ifp->pim_ifstat_prune_recv,
    5100             :                                 pim_ifp->pim_ifstat_prune_send,
    5101             :                                 pim_ifp->pim_ifstat_reg_recv,
    5102             :                                 pim_ifp->pim_ifstat_reg_send,
    5103             :                                 pim_ifp->pim_ifstat_reg_stop_recv,
    5104             :                                 pim_ifp->pim_ifstat_reg_stop_send,
    5105             :                                 pim_ifp->pim_ifstat_assert_recv,
    5106             :                                 pim_ifp->pim_ifstat_assert_send,
    5107             :                                 pim_ifp->pim_ifstat_bsm_rx,
    5108             :                                 pim_ifp->pim_ifstat_bsm_tx);
    5109             :                 }
    5110             :         }
    5111           0 :         if (uj)
    5112           0 :                 vty_json(vty, json);
    5113           0 : }
    5114             : 
    5115           0 : void pim_show_interface_traffic_single(struct pim_instance *pim,
    5116             :                                        struct vty *vty, const char *ifname,
    5117             :                                        bool uj)
    5118             : {
    5119           0 :         struct interface *ifp = NULL;
    5120           0 :         struct pim_interface *pim_ifp = NULL;
    5121           0 :         json_object *json = NULL;
    5122           0 :         json_object *json_row = NULL;
    5123           0 :         uint8_t found_ifname = 0;
    5124             : 
    5125           0 :         if (uj)
    5126           0 :                 json = json_object_new_object();
    5127             :         else {
    5128           0 :                 vty_out(vty, "\n");
    5129           0 :                 vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
    5130             :                         "Interface", "    HELLO", "    JOIN", "   PRUNE",
    5131             :                         "   REGISTER", "  REGISTER-STOP", "  ASSERT",
    5132             :                         "    BSM");
    5133           0 :                 vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
    5134             :                         "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
    5135             :                         "     Rx/Tx", "    Rx/Tx", "    Rx/Tx");
    5136           0 :                 vty_out(vty,
    5137             :                         "-------------------------------------------------------------------------------------------------------------------------------\n");
    5138             :         }
    5139             : 
    5140           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    5141           0 :                 if (strcmp(ifname, ifp->name))
    5142           0 :                         continue;
    5143             : 
    5144           0 :                 pim_ifp = ifp->info;
    5145             : 
    5146           0 :                 if (!pim_ifp)
    5147           0 :                         continue;
    5148             : 
    5149           0 :                 found_ifname = 1;
    5150           0 :                 if (uj) {
    5151           0 :                         json_row = json_object_new_object();
    5152           0 :                         json_object_pim_ifp_add(json_row, ifp);
    5153           0 :                         json_object_int_add(json_row, "helloRx",
    5154           0 :                                             pim_ifp->pim_ifstat_hello_recv);
    5155           0 :                         json_object_int_add(json_row, "helloTx",
    5156           0 :                                             pim_ifp->pim_ifstat_hello_sent);
    5157           0 :                         json_object_int_add(json_row, "joinRx",
    5158           0 :                                             pim_ifp->pim_ifstat_join_recv);
    5159           0 :                         json_object_int_add(json_row, "joinTx",
    5160           0 :                                             pim_ifp->pim_ifstat_join_send);
    5161           0 :                         json_object_int_add(json_row, "pruneRx",
    5162           0 :                                             pim_ifp->pim_ifstat_prune_recv);
    5163           0 :                         json_object_int_add(json_row, "pruneTx",
    5164           0 :                                             pim_ifp->pim_ifstat_prune_send);
    5165           0 :                         json_object_int_add(json_row, "registerRx",
    5166           0 :                                             pim_ifp->pim_ifstat_reg_recv);
    5167           0 :                         json_object_int_add(json_row, "registerTx",
    5168           0 :                                             pim_ifp->pim_ifstat_reg_send);
    5169           0 :                         json_object_int_add(json_row, "registerStopRx",
    5170           0 :                                             pim_ifp->pim_ifstat_reg_stop_recv);
    5171           0 :                         json_object_int_add(json_row, "registerStopTx",
    5172           0 :                                             pim_ifp->pim_ifstat_reg_stop_send);
    5173           0 :                         json_object_int_add(json_row, "assertRx",
    5174           0 :                                             pim_ifp->pim_ifstat_assert_recv);
    5175           0 :                         json_object_int_add(json_row, "assertTx",
    5176           0 :                                             pim_ifp->pim_ifstat_assert_send);
    5177           0 :                         json_object_int_add(json_row, "bsmRx",
    5178           0 :                                             pim_ifp->pim_ifstat_bsm_rx);
    5179           0 :                         json_object_int_add(json_row, "bsmTx",
    5180           0 :                                             pim_ifp->pim_ifstat_bsm_tx);
    5181             : 
    5182           0 :                         json_object_object_add(json, ifp->name, json_row);
    5183             :                 } else {
    5184           0 :                         vty_out(vty,
    5185             :                                 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
    5186             :                                 "/%-7" PRIu64 "\n",
    5187             :                                 ifp->name, pim_ifp->pim_ifstat_hello_recv,
    5188             :                                 pim_ifp->pim_ifstat_hello_sent,
    5189             :                                 pim_ifp->pim_ifstat_join_recv,
    5190             :                                 pim_ifp->pim_ifstat_join_send,
    5191             :                                 pim_ifp->pim_ifstat_prune_recv,
    5192             :                                 pim_ifp->pim_ifstat_prune_send,
    5193             :                                 pim_ifp->pim_ifstat_reg_recv,
    5194             :                                 pim_ifp->pim_ifstat_reg_send,
    5195             :                                 pim_ifp->pim_ifstat_reg_stop_recv,
    5196             :                                 pim_ifp->pim_ifstat_reg_stop_send,
    5197             :                                 pim_ifp->pim_ifstat_assert_recv,
    5198             :                                 pim_ifp->pim_ifstat_assert_send,
    5199             :                                 pim_ifp->pim_ifstat_bsm_rx,
    5200             :                                 pim_ifp->pim_ifstat_bsm_tx);
    5201             :                 }
    5202             :         }
    5203           0 :         if (uj)
    5204           0 :                 vty_json(vty, json);
    5205           0 :         else if (!found_ifname)
    5206           0 :                 vty_out(vty, "%% No such interface\n");
    5207           0 : }
    5208             : 
    5209           0 : int pim_show_interface_traffic_helper(const char *vrf, const char *if_name,
    5210             :                                       struct vty *vty, bool uj)
    5211             : {
    5212           0 :         struct pim_instance *pim;
    5213           0 :         struct vrf *v;
    5214             : 
    5215           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    5216             : 
    5217           0 :         if (!v)
    5218             :                 return CMD_WARNING;
    5219             : 
    5220           0 :         pim = v->info;
    5221             : 
    5222           0 :         if (!pim) {
    5223           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    5224           0 :                 return CMD_WARNING;
    5225             :         }
    5226             : 
    5227           0 :         if (if_name)
    5228           0 :                 pim_show_interface_traffic_single(v->info, vty, if_name, uj);
    5229             :         else
    5230           0 :                 pim_show_interface_traffic(v->info, vty, uj);
    5231             : 
    5232             :         return CMD_SUCCESS;
    5233             : }
    5234             : 
    5235           0 : void clear_pim_interfaces(struct pim_instance *pim)
    5236             : {
    5237           0 :         struct interface *ifp;
    5238             : 
    5239           0 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
    5240           0 :                 if (ifp->info)
    5241           0 :                         pim_neighbor_delete_all(ifp, "interface cleared");
    5242             :         }
    5243           0 : }
    5244             : 
    5245          10 : void pim_show_bsr(struct pim_instance *pim, struct vty *vty, bool uj)
    5246             : {
    5247          10 :         char uptime[10];
    5248          10 :         char last_bsm_seen[10];
    5249          10 :         time_t now;
    5250          10 :         char bsr_state[20];
    5251          10 :         json_object *json = NULL;
    5252             : 
    5253          10 :         if (pim_addr_is_any(pim->global_scope.current_bsr)) {
    5254           6 :                 pim_time_uptime(uptime, sizeof(uptime),
    5255             :                                 pim->global_scope.current_bsr_first_ts);
    5256           6 :                 pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
    5257             :                                 pim->global_scope.current_bsr_last_ts);
    5258             :         }
    5259             : 
    5260             :         else {
    5261           4 :                 now = pim_time_monotonic_sec();
    5262           4 :                 pim_time_uptime(uptime, sizeof(uptime),
    5263           4 :                                 (now - pim->global_scope.current_bsr_first_ts));
    5264           4 :                 pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
    5265           4 :                                 now - pim->global_scope.current_bsr_last_ts);
    5266             :         }
    5267             : 
    5268          10 :         switch (pim->global_scope.state) {
    5269           6 :         case NO_INFO:
    5270           6 :                 strlcpy(bsr_state, "NO_INFO", sizeof(bsr_state));
    5271           6 :                 break;
    5272           0 :         case ACCEPT_ANY:
    5273           0 :                 strlcpy(bsr_state, "ACCEPT_ANY", sizeof(bsr_state));
    5274           0 :                 break;
    5275           4 :         case ACCEPT_PREFERRED:
    5276           4 :                 strlcpy(bsr_state, "ACCEPT_PREFERRED", sizeof(bsr_state));
    5277           4 :                 break;
    5278           0 :         default:
    5279           0 :                 strlcpy(bsr_state, "", sizeof(bsr_state));
    5280             :         }
    5281             : 
    5282             : 
    5283          10 :         if (uj) {
    5284          10 :                 json = json_object_new_object();
    5285          10 :                 json_object_string_addf(json, "bsr", "%pPA",
    5286             :                                         &pim->global_scope.current_bsr);
    5287          10 :                 json_object_int_add(json, "priority",
    5288          10 :                                     pim->global_scope.current_bsr_prio);
    5289          10 :                 json_object_int_add(json, "fragmentTag",
    5290          10 :                                     pim->global_scope.bsm_frag_tag);
    5291          10 :                 json_object_string_add(json, "state", bsr_state);
    5292          10 :                 json_object_string_add(json, "upTime", uptime);
    5293          10 :                 json_object_string_add(json, "lastBsmSeen", last_bsm_seen);
    5294             :         }
    5295             : 
    5296             :         else {
    5297           0 :                 vty_out(vty, "PIMv2 Bootstrap information\n");
    5298           0 :                 vty_out(vty, "Current preferred BSR address: %pPA\n",
    5299             :                         &pim->global_scope.current_bsr);
    5300           0 :                 vty_out(vty,
    5301             :                         "Priority        Fragment-Tag       State           UpTime\n");
    5302           0 :                 vty_out(vty, "  %-12d    %-12d    %-13s    %7s\n",
    5303             :                         pim->global_scope.current_bsr_prio,
    5304           0 :                         pim->global_scope.bsm_frag_tag, bsr_state, uptime);
    5305           0 :                 vty_out(vty, "Last BSM seen: %s\n", last_bsm_seen);
    5306             :         }
    5307             : 
    5308          10 :         if (uj)
    5309          10 :                 vty_json(vty, json);
    5310          10 : }
    5311             : 
    5312          10 : int pim_show_bsr_helper(const char *vrf, struct vty *vty, bool uj)
    5313             : {
    5314          10 :         struct pim_instance *pim;
    5315          10 :         struct vrf *v;
    5316             : 
    5317          10 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    5318             : 
    5319          10 :         if (!v)
    5320             :                 return CMD_WARNING;
    5321             : 
    5322          10 :         pim = pim_get_pim_instance(v->vrf_id);
    5323             : 
    5324          10 :         if (!pim) {
    5325           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    5326           0 :                 return CMD_WARNING;
    5327             :         }
    5328             : 
    5329          10 :         pim_show_bsr(v->info, vty, uj);
    5330             : 
    5331          10 :         return CMD_SUCCESS;
    5332             : }
    5333             : 
    5334             : /*Display the group-rp mappings */
    5335           0 : static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
    5336             :                                             struct vty *vty, bool uj)
    5337             : {
    5338           0 :         struct bsgrp_node *bsgrp;
    5339           0 :         struct bsm_rpinfo *bsm_rp;
    5340           0 :         struct route_node *rn;
    5341           0 :         json_object *json = NULL;
    5342           0 :         json_object *json_group = NULL;
    5343           0 :         json_object *json_row = NULL;
    5344           0 :         struct ttable *tt = NULL;
    5345             : 
    5346           0 :         if (uj) {
    5347           0 :                 json = json_object_new_object();
    5348           0 :                 json_object_string_addf(json, "BSR Address", "%pPA",
    5349             :                                         &pim->global_scope.current_bsr);
    5350             :         } else
    5351           0 :                 vty_out(vty, "BSR Address  %pPA\n",
    5352             :                         &pim->global_scope.current_bsr);
    5353             : 
    5354           0 :         for (rn = route_top(pim->global_scope.bsrp_table); rn;
    5355           0 :              rn = route_next(rn)) {
    5356           0 :                 bsgrp = (struct bsgrp_node *)rn->info;
    5357             : 
    5358           0 :                 if (!bsgrp)
    5359           0 :                         continue;
    5360             : 
    5361           0 :                 char grp_str[PREFIX_STRLEN];
    5362             : 
    5363           0 :                 prefix2str(&bsgrp->group, grp_str, sizeof(grp_str));
    5364             : 
    5365           0 :                 if (uj) {
    5366           0 :                         json_object_object_get_ex(json, grp_str, &json_group);
    5367           0 :                         if (!json_group) {
    5368           0 :                                 json_group = json_object_new_object();
    5369           0 :                                 json_object_object_add(json, grp_str,
    5370             :                                                        json_group);
    5371             :                         }
    5372             :                 } else {
    5373           0 :                         vty_out(vty, "Group Address %pFX\n", &bsgrp->group);
    5374           0 :                         vty_out(vty, "--------------------------\n");
    5375             :                         /* Prepare table. */
    5376           0 :                         tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    5377           0 :                         ttable_add_row(tt, "Rp Address|priority|Holdtime|Hash");
    5378           0 :                         tt->style.cell.rpad = 2;
    5379           0 :                         tt->style.corner = '+';
    5380           0 :                         ttable_restyle(tt);
    5381             : 
    5382           0 :                         ttable_add_row(tt, "%s|%c|%c|%c", "(ACTIVE)", ' ', ' ',
    5383             :                                        ' ');
    5384             :                 }
    5385             : 
    5386           0 :                 frr_each (bsm_rpinfos, bsgrp->bsrp_list, bsm_rp) {
    5387           0 :                         if (uj) {
    5388           0 :                                 json_row = json_object_new_object();
    5389           0 :                                 json_object_string_addf(json_row, "Rp Address",
    5390             :                                                         "%pPA",
    5391             :                                                         &bsm_rp->rp_address);
    5392           0 :                                 json_object_int_add(json_row, "Rp HoldTime",
    5393           0 :                                                     bsm_rp->rp_holdtime);
    5394           0 :                                 json_object_int_add(json_row, "Rp Priority",
    5395           0 :                                                     bsm_rp->rp_prio);
    5396           0 :                                 json_object_int_add(json_row, "Hash Val",
    5397           0 :                                                     bsm_rp->hash);
    5398           0 :                                 json_object_object_addf(json_group, json_row,
    5399             :                                                         "%pPA",
    5400             :                                                         &bsm_rp->rp_address);
    5401             : 
    5402             :                         } else {
    5403           0 :                                 ttable_add_row(
    5404             :                                         tt, "%pPA|%u|%u|%u",
    5405           0 :                                         &bsm_rp->rp_address, bsm_rp->rp_prio,
    5406           0 :                                         bsm_rp->rp_holdtime, bsm_rp->hash);
    5407             :                         }
    5408             :                 }
    5409             :                 /* Dump the generated table. */
    5410           0 :                 if (tt) {
    5411           0 :                         char *table = NULL;
    5412             : 
    5413           0 :                         table = ttable_dump(tt, "\n");
    5414           0 :                         vty_out(vty, "%s\n", table);
    5415           0 :                         XFREE(MTYPE_TMP, table);
    5416           0 :                         ttable_del(tt);
    5417           0 :                         tt = NULL;
    5418             :                 }
    5419           0 :                 if (!bsm_rpinfos_count(bsgrp->bsrp_list) && !uj)
    5420           0 :                         vty_out(vty, "Active List is empty.\n");
    5421             : 
    5422           0 :                 if (uj) {
    5423           0 :                         json_object_int_add(json_group, "Pending RP count",
    5424           0 :                                             bsgrp->pend_rp_cnt);
    5425             :                 } else {
    5426           0 :                         vty_out(vty, "(PENDING)\n");
    5427           0 :                         vty_out(vty, "Pending RP count :%d\n",
    5428             :                                 bsgrp->pend_rp_cnt);
    5429           0 :                         if (bsgrp->pend_rp_cnt) {
    5430             :                                 /* Prepare table. */
    5431           0 :                                 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
    5432           0 :                                 ttable_add_row(
    5433             :                                         tt,
    5434             :                                         "Rp Address|priority|Holdtime|Hash");
    5435           0 :                                 tt->style.cell.rpad = 2;
    5436           0 :                                 tt->style.corner = '+';
    5437           0 :                                 ttable_restyle(tt);
    5438             :                         }
    5439             :                 }
    5440             : 
    5441           0 :                 frr_each (bsm_rpinfos, bsgrp->partial_bsrp_list, bsm_rp) {
    5442           0 :                         if (uj) {
    5443           0 :                                 json_row = json_object_new_object();
    5444           0 :                                 json_object_string_addf(json_row, "Rp Address",
    5445             :                                                         "%pPA",
    5446             :                                                         &bsm_rp->rp_address);
    5447           0 :                                 json_object_int_add(json_row, "Rp HoldTime",
    5448           0 :                                                     bsm_rp->rp_holdtime);
    5449           0 :                                 json_object_int_add(json_row, "Rp Priority",
    5450           0 :                                                     bsm_rp->rp_prio);
    5451           0 :                                 json_object_int_add(json_row, "Hash Val",
    5452           0 :                                                     bsm_rp->hash);
    5453           0 :                                 json_object_object_addf(json_group, json_row,
    5454             :                                                         "%pPA",
    5455             :                                                         &bsm_rp->rp_address);
    5456             :                         } else {
    5457           0 :                                 ttable_add_row(
    5458             :                                         tt, "%pPA|%u|%u|%u",
    5459           0 :                                         &bsm_rp->rp_address, bsm_rp->rp_prio,
    5460           0 :                                         bsm_rp->rp_holdtime, bsm_rp->hash);
    5461             :                         }
    5462             :                 }
    5463             :                 /* Dump the generated table. */
    5464           0 :                 if (tt) {
    5465           0 :                         char *table = NULL;
    5466             : 
    5467           0 :                         table = ttable_dump(tt, "\n");
    5468           0 :                         vty_out(vty, "%s\n", table);
    5469           0 :                         XFREE(MTYPE_TMP, table);
    5470           0 :                         ttable_del(tt);
    5471             :                 }
    5472           0 :                 if (!bsm_rpinfos_count(bsgrp->partial_bsrp_list) && !uj)
    5473           0 :                         vty_out(vty, "Partial List is empty\n");
    5474             : 
    5475           0 :                 if (!uj)
    5476           0 :                         vty_out(vty, "\n");
    5477             :         }
    5478             : 
    5479           0 :         if (uj)
    5480           0 :                 vty_json(vty, json);
    5481           0 : }
    5482             : 
    5483           0 : int pim_show_group_rp_mappings_info_helper(const char *vrf, struct vty *vty,
    5484             :                                            bool uj)
    5485             : {
    5486           0 :         struct pim_instance *pim;
    5487           0 :         struct vrf *v;
    5488             : 
    5489           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    5490             : 
    5491           0 :         if (!v)
    5492             :                 return CMD_WARNING;
    5493             : 
    5494           0 :         pim = v->info;
    5495             : 
    5496           0 :         if (!pim) {
    5497           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    5498           0 :                 return CMD_WARNING;
    5499             :         }
    5500             : 
    5501           0 :         pim_show_group_rp_mappings_info(v->info, vty, uj);
    5502             : 
    5503           0 :         return CMD_SUCCESS;
    5504             : }
    5505             : 
    5506             : /* Display the bsm database details */
    5507           0 : static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
    5508             : {
    5509           0 :         int count = 0;
    5510           0 :         int fragment = 1;
    5511           0 :         struct bsm_frag *bsfrag;
    5512           0 :         json_object *json = NULL;
    5513           0 :         json_object *json_group = NULL;
    5514           0 :         json_object *json_row = NULL;
    5515             : 
    5516           0 :         count = bsm_frags_count(pim->global_scope.bsm_frags);
    5517             : 
    5518           0 :         if (uj) {
    5519           0 :                 json = json_object_new_object();
    5520           0 :                 json_object_int_add(json, "Number of the fragments", count);
    5521             :         } else {
    5522           0 :                 vty_out(vty, "Scope Zone: Global\n");
    5523           0 :                 vty_out(vty, "Number of the fragments: %d\n", count);
    5524           0 :                 vty_out(vty, "\n");
    5525             :         }
    5526             : 
    5527           0 :         frr_each (bsm_frags, pim->global_scope.bsm_frags, bsfrag) {
    5528           0 :                 char grp_str[PREFIX_STRLEN];
    5529           0 :                 struct bsmmsg_grpinfo *group;
    5530           0 :                 struct bsmmsg_rpinfo *bsm_rpinfo;
    5531           0 :                 struct prefix grp;
    5532           0 :                 struct bsm_hdr *hdr;
    5533           0 :                 pim_addr bsr_addr;
    5534           0 :                 uint32_t offset = 0;
    5535           0 :                 uint8_t *buf;
    5536           0 :                 uint32_t len = 0;
    5537           0 :                 uint32_t frag_rp_cnt = 0;
    5538             : 
    5539           0 :                 buf = bsfrag->data;
    5540           0 :                 len = bsfrag->size;
    5541             : 
    5542             :                 /* skip pim header */
    5543           0 :                 buf += PIM_MSG_HEADER_LEN;
    5544           0 :                 len -= PIM_MSG_HEADER_LEN;
    5545             : 
    5546           0 :                 hdr = (struct bsm_hdr *)buf;
    5547             :                 /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */
    5548           0 :                 memcpy(&bsr_addr, &hdr->bsr_addr.addr, sizeof(bsr_addr));
    5549             : 
    5550             :                 /* BSM starts with bsr header */
    5551           0 :                 buf += sizeof(struct bsm_hdr);
    5552           0 :                 len -= sizeof(struct bsm_hdr);
    5553             : 
    5554           0 :                 if (uj) {
    5555           0 :                         json_object_string_addf(json, "BSR address", "%pPA",
    5556             :                                                 &bsr_addr);
    5557           0 :                         json_object_int_add(json, "BSR priority",
    5558           0 :                                             hdr->bsr_prio);
    5559           0 :                         json_object_int_add(json, "Hashmask Length",
    5560           0 :                                             hdr->hm_len);
    5561           0 :                         json_object_int_add(json, "Fragment Tag",
    5562           0 :                                             ntohs(hdr->frag_tag));
    5563             :                 } else {
    5564           0 :                         vty_out(vty, "BSM Fragment : %d\n", fragment);
    5565           0 :                         vty_out(vty, "------------------\n");
    5566           0 :                         vty_out(vty, "%-15s %-15s %-15s %-15s\n", "BSR-Address",
    5567             :                                 "BSR-Priority", "Hashmask-len", "Fragment-Tag");
    5568           0 :                         vty_out(vty, "%-15pPA %-15d %-15d %-15d\n", &bsr_addr,
    5569           0 :                                 hdr->bsr_prio, hdr->hm_len,
    5570           0 :                                 ntohs(hdr->frag_tag));
    5571             :                 }
    5572             : 
    5573           0 :                 vty_out(vty, "\n");
    5574             : 
    5575           0 :                 while (offset < len) {
    5576           0 :                         group = (struct bsmmsg_grpinfo *)buf;
    5577             : 
    5578           0 :                         if (group->group.family == PIM_MSG_ADDRESS_FAMILY_IPV4)
    5579           0 :                                 grp.family = AF_INET;
    5580           0 :                         else if (group->group.family ==
    5581             :                                  PIM_MSG_ADDRESS_FAMILY_IPV6)
    5582           0 :                                 grp.family = AF_INET6;
    5583             : 
    5584           0 :                         grp.prefixlen = group->group.mask;
    5585             : #if PIM_IPV == 4
    5586           0 :                         grp.u.prefix4 = group->group.addr;
    5587             : #else
    5588           0 :                         grp.u.prefix6 = group->group.addr;
    5589             : #endif
    5590             : 
    5591           0 :                         prefix2str(&grp, grp_str, sizeof(grp_str));
    5592             : 
    5593           0 :                         buf += sizeof(struct bsmmsg_grpinfo);
    5594           0 :                         offset += sizeof(struct bsmmsg_grpinfo);
    5595             : 
    5596           0 :                         if (uj) {
    5597           0 :                                 json_object_object_get_ex(json, grp_str,
    5598             :                                                           &json_group);
    5599           0 :                                 if (!json_group) {
    5600           0 :                                         json_group = json_object_new_object();
    5601           0 :                                         json_object_int_add(json_group,
    5602             :                                                             "Rp Count",
    5603           0 :                                                             group->rp_count);
    5604           0 :                                         json_object_int_add(
    5605             :                                                 json_group, "Fragment Rp count",
    5606           0 :                                                 group->frag_rp_count);
    5607           0 :                                         json_object_object_add(json, grp_str,
    5608             :                                                                json_group);
    5609             :                                 }
    5610             :                         } else {
    5611           0 :                                 vty_out(vty, "Group : %s\n", grp_str);
    5612           0 :                                 vty_out(vty, "-------------------\n");
    5613           0 :                                 vty_out(vty, "Rp Count:%d\n", group->rp_count);
    5614           0 :                                 vty_out(vty, "Fragment Rp Count : %d\n",
    5615           0 :                                         group->frag_rp_count);
    5616             :                         }
    5617             : 
    5618           0 :                         frag_rp_cnt = group->frag_rp_count;
    5619             : 
    5620           0 :                         if (!frag_rp_cnt)
    5621           0 :                                 continue;
    5622             : 
    5623           0 :                         if (!uj)
    5624           0 :                                 vty_out(vty,
    5625             :                                         "RpAddress     HoldTime     Priority\n");
    5626             : 
    5627           0 :                         while (frag_rp_cnt--) {
    5628           0 :                                 pim_addr rp_addr;
    5629             : 
    5630           0 :                                 bsm_rpinfo = (struct bsmmsg_rpinfo *)buf;
    5631             :                                 /* unaligned, again */
    5632           0 :                                 memcpy(&rp_addr, &bsm_rpinfo->rpaddr.addr,
    5633             :                                        sizeof(rp_addr));
    5634             : 
    5635           0 :                                 buf += sizeof(struct bsmmsg_rpinfo);
    5636           0 :                                 offset += sizeof(struct bsmmsg_rpinfo);
    5637             : 
    5638           0 :                                 if (uj) {
    5639           0 :                                         json_row = json_object_new_object();
    5640           0 :                                         json_object_string_addf(
    5641             :                                                 json_row, "Rp Address", "%pPA",
    5642             :                                                 &rp_addr);
    5643           0 :                                         json_object_int_add(
    5644             :                                                 json_row, "Rp HoldTime",
    5645           0 :                                                 ntohs(bsm_rpinfo->rp_holdtime));
    5646           0 :                                         json_object_int_add(json_row,
    5647             :                                                             "Rp Priority",
    5648           0 :                                                             bsm_rpinfo->rp_pri);
    5649           0 :                                         json_object_object_addf(
    5650             :                                                 json_group, json_row, "%pPA",
    5651             :                                                 &rp_addr);
    5652             :                                 } else {
    5653           0 :                                         vty_out(vty, "%-15pPA %-12d %d\n",
    5654             :                                                 &rp_addr,
    5655           0 :                                                 ntohs(bsm_rpinfo->rp_holdtime),
    5656           0 :                                                 bsm_rpinfo->rp_pri);
    5657             :                                 }
    5658             :                         }
    5659           0 :                         vty_out(vty, "\n");
    5660             :                 }
    5661             : 
    5662           0 :                 fragment++;
    5663             :         }
    5664             : 
    5665           0 :         if (uj)
    5666           0 :                 vty_json(vty, json);
    5667           0 : }
    5668             : 
    5669           0 : int pim_show_bsm_db_helper(const char *vrf, struct vty *vty, bool uj)
    5670             : {
    5671           0 :         struct pim_instance *pim;
    5672           0 :         struct vrf *v;
    5673             : 
    5674           0 :         v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
    5675             : 
    5676           0 :         if (!v)
    5677             :                 return CMD_WARNING;
    5678             : 
    5679           0 :         pim = v->info;
    5680             : 
    5681           0 :         if (!pim) {
    5682           0 :                 vty_out(vty, "%% Unable to find pim instance\n");
    5683           0 :                 return CMD_WARNING;
    5684             :         }
    5685             : 
    5686           0 :         pim_show_bsm_db(v->info, vty, uj);
    5687             : 
    5688           0 :         return CMD_SUCCESS;
    5689             : }

Generated by: LCOV version v1.16-topotato