]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: Moving the common functions from pim_cmd.c file
authorSai Gomathi N <nsaigomathi@vmware.com>
Tue, 8 Feb 2022 17:14:26 +0000 (09:14 -0800)
committerSai Gomathi N <nsaigomathi@vmware.com>
Mon, 4 Apr 2022 07:52:02 +0000 (00:52 -0700)
Moving the functions that are used by both IPV4 and IPV6 to a
common file pim_cmd_common.c file

Signed-off-by: Sai Gomathi N <nsaigomathi@vmware.com>
pimd/pim_cmd.c
pimd/pim_cmd_common.c
pimd/pim_cmd_common.h

index 633bacadc9380c84d93ad14585f7484da930bbe9..67e32c8e4a212d6e30ecadf1b6453efa2dd55841 100644 (file)
@@ -292,180 +292,6 @@ static void pim_show_assert_winner_metric(struct pim_instance *pim,
        }
 }
 
-static void json_object_pim_ifp_add(struct json_object *json,
-                                   struct interface *ifp)
-{
-       struct pim_interface *pim_ifp;
-
-       pim_ifp = ifp->info;
-       json_object_string_add(json, "name", ifp->name);
-       json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
-       json_object_string_addf(json, "address", "%pI4",
-                               &pim_ifp->primary_address);
-       json_object_int_add(json, "index", ifp->ifindex);
-
-       if (if_is_multicast(ifp))
-               json_object_boolean_true_add(json, "flagMulticast");
-
-       if (if_is_broadcast(ifp))
-               json_object_boolean_true_add(json, "flagBroadcast");
-
-       if (ifp->flags & IFF_ALLMULTI)
-               json_object_boolean_true_add(json, "flagAllMulticast");
-
-       if (ifp->flags & IFF_PROMISC)
-               json_object_boolean_true_add(json, "flagPromiscuous");
-
-       if (PIM_IF_IS_DELETED(ifp))
-               json_object_boolean_true_add(json, "flagDeleted");
-
-       if (pim_if_lan_delay_enabled(ifp))
-               json_object_boolean_true_add(json, "lanDelayEnabled");
-}
-
-static void pim_show_membership_helper(struct vty *vty,
-                                      struct pim_interface *pim_ifp,
-                                      struct pim_ifchannel *ch,
-                                      struct json_object *json)
-{
-       char ch_grp_str[PIM_ADDRSTRLEN];
-       json_object *json_iface = NULL;
-       json_object *json_row = NULL;
-
-       json_object_object_get_ex(json, ch->interface->name, &json_iface);
-       if (!json_iface) {
-               json_iface = json_object_new_object();
-               json_object_pim_ifp_add(json_iface, ch->interface);
-               json_object_object_add(json, ch->interface->name, json_iface);
-       }
-
-       snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs", &ch->sg.grp);
-
-       json_row = json_object_new_object();
-       json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
-       json_object_string_add(json_row, "group", ch_grp_str);
-       json_object_string_add(json_row, "localMembership",
-                              ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
-                              ? "NOINFO"
-                              : "INCLUDE");
-       json_object_object_add(json_iface, ch_grp_str, json_row);
-}
-
-static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
-                               bool uj)
-{
-       struct pim_interface *pim_ifp;
-       struct pim_ifchannel *ch;
-       struct interface *ifp;
-       enum json_type type;
-       json_object *json = NULL;
-       json_object *json_tmp = NULL;
-
-       json = json_object_new_object();
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               pim_ifp = ifp->info;
-               if (!pim_ifp)
-                       continue;
-
-               RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
-                       pim_show_membership_helper(vty, pim_ifp, ch, json);
-               } /* scan interface channels */
-       }
-
-       if (uj) {
-               vty_out(vty, "%s\n", json_object_to_json_string_ext(
-                               json, JSON_C_TO_STRING_PRETTY));
-       } else {
-               vty_out(vty,
-                       "Interface         Address          Source           Group            Membership\n");
-
-               /*
-                * Example of the json data we are traversing
-                *
-                * {
-                *   "swp3":{
-                *     "name":"swp3",
-                *     "state":"up",
-                *     "address":"10.1.20.1",
-                *     "index":5,
-                *     "flagMulticast":true,
-                *     "flagBroadcast":true,
-                *     "lanDelayEnabled":true,
-                *     "226.10.10.10":{
-                *       "source":"*",
-                *       "group":"226.10.10.10",
-                *       "localMembership":"INCLUDE"
-                *     }
-                *   }
-                * }
-                */
-
-               /* foreach interface */
-               json_object_object_foreach(json, key, val)
-               {
-
-                       /* Find all of the keys where the val is an object. In
-                        * the example
-                        * above the only one is 226.10.10.10
-                        */
-                       json_object_object_foreach(val, if_field_key,
-                                                  if_field_val)
-                       {
-                               type = json_object_get_type(if_field_val);
-
-                               if (type == json_type_object) {
-                                       vty_out(vty, "%-16s  ", key);
-
-                                       json_object_object_get_ex(
-                                               val, "address", &json_tmp);
-                                       vty_out(vty, "%-15s  ",
-                                               json_object_get_string(
-                                                       json_tmp));
-
-                                       json_object_object_get_ex(if_field_val,
-                                                                 "source",
-                                                                 &json_tmp);
-                                       vty_out(vty, "%-15s  ",
-                                               json_object_get_string(
-                                                       json_tmp));
-
-                                       /* Group */
-                                       vty_out(vty, "%-15s  ", if_field_key);
-
-                                       json_object_object_get_ex(
-                                               if_field_val, "localMembership",
-                                               &json_tmp);
-                                       vty_out(vty, "%-10s\n",
-                                               json_object_get_string(
-                                                       json_tmp));
-                               }
-                       }
-               }
-       }
-
-       json_object_free(json);
-}
-
-static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
-{
-       vty_out(vty, "Flags\n");
-       vty_out(vty, "-----\n");
-       vty_out(vty, "All Multicast   : %s\n",
-               (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
-       vty_out(vty, "Broadcast       : %s\n",
-               if_is_broadcast(ifp) ? "yes" : "no");
-       vty_out(vty, "Deleted         : %s\n",
-               PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
-       vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
-       vty_out(vty, "Multicast       : %s\n",
-               if_is_multicast(ifp) ? "yes" : "no");
-       vty_out(vty, "Promiscuous     : %s\n",
-               (ifp->flags & IFF_PROMISC) ? "yes" : "no");
-       vty_out(vty, "\n");
-       vty_out(vty, "\n");
-}
-
 static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
                                 bool uj)
 {
@@ -866,412 +692,6 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty,
                vty_json(vty, json);
 }
 
-static void pim_show_interfaces_single(struct pim_instance *pim,
-                                      struct vty *vty, const char *ifname,
-                                      bool mlag, bool uj)
-{
-       struct in_addr ifaddr;
-       struct interface *ifp;
-       struct listnode *neighnode;
-       struct pim_interface *pim_ifp;
-       struct pim_neighbor *neigh;
-       struct pim_upstream *up;
-       time_t now;
-       char dr_str[INET_ADDRSTRLEN];
-       char dr_uptime[10];
-       char expire[10];
-       char grp_str[INET_ADDRSTRLEN];
-       char hello_period[10];
-       char hello_timer[10];
-       char neigh_src_str[INET_ADDRSTRLEN];
-       char src_str[INET_ADDRSTRLEN];
-       char stat_uptime[10];
-       char uptime[10];
-       int found_ifname = 0;
-       int print_header;
-       json_object *json = NULL;
-       json_object *json_row = NULL;
-       json_object *json_pim_neighbor = NULL;
-       json_object *json_pim_neighbors = NULL;
-       json_object *json_group = NULL;
-       json_object *json_group_source = NULL;
-       json_object *json_fhr_sources = NULL;
-       struct pim_secondary_addr *sec_addr;
-       struct listnode *sec_node;
-
-       now = pim_time_monotonic_sec();
-
-       if (uj)
-               json = json_object_new_object();
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               pim_ifp = ifp->info;
-
-               if (!pim_ifp)
-                       continue;
-
-               if (mlag == true && pim_ifp->activeactive == false)
-                       continue;
-
-               if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
-                       continue;
-
-               found_ifname = 1;
-               ifaddr = pim_ifp->primary_address;
-               pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str,
-                              sizeof(dr_str));
-               pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
-                                     pim_ifp->pim_dr_election_last);
-               pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
-                                        pim_ifp->t_pim_hello_timer);
-               pim_time_mmss(hello_period, sizeof(hello_period),
-                             pim_ifp->pim_hello_period);
-               pim_time_uptime(stat_uptime, sizeof(stat_uptime),
-                               now - pim_ifp->pim_ifstat_start);
-
-               if (uj) {
-                       char pbuf[PREFIX2STR_BUFFER];
-                       json_row = json_object_new_object();
-                       json_object_pim_ifp_add(json_row, ifp);
-
-                       if (pim_ifp->update_source.s_addr != INADDR_ANY) {
-                               json_object_string_addf(
-                                       json_row, "useSource", "%pI4",
-                                       &pim_ifp->update_source);
-                       }
-                       if (pim_ifp->sec_addr_list) {
-                               json_object *sec_list = NULL;
-
-                               sec_list = json_object_new_array();
-                               for (ALL_LIST_ELEMENTS_RO(
-                                            pim_ifp->sec_addr_list, sec_node,
-                                            sec_addr)) {
-                                       json_object_array_add(
-                                               sec_list,
-                                               json_object_new_string(
-                                                       prefix2str(
-                                                               &sec_addr->addr,
-                                                               pbuf,
-                                                               sizeof(pbuf))));
-                               }
-                               json_object_object_add(json_row,
-                                                      "secondaryAddressList",
-                                                      sec_list);
-                       }
-
-                       // PIM neighbors
-                       if (pim_ifp->pim_neighbor_list->count) {
-                               json_pim_neighbors = json_object_new_object();
-
-                               for (ALL_LIST_ELEMENTS_RO(
-                                            pim_ifp->pim_neighbor_list,
-                                            neighnode, neigh)) {
-                                       json_pim_neighbor =
-                                               json_object_new_object();
-                                       pim_inet4_dump("<src?>",
-                                                      neigh->source_addr,
-                                                      neigh_src_str,
-                                                      sizeof(neigh_src_str));
-                                       pim_time_uptime(uptime, sizeof(uptime),
-                                                       now - neigh->creation);
-                                       pim_time_timer_to_hhmmss(
-                                               expire, sizeof(expire),
-                                               neigh->t_expire_timer);
-
-                                       json_object_string_add(
-                                               json_pim_neighbor, "address",
-                                               neigh_src_str);
-                                       json_object_string_add(
-                                               json_pim_neighbor, "upTime",
-                                               uptime);
-                                       json_object_string_add(
-                                               json_pim_neighbor, "holdtime",
-                                               expire);
-
-                                       json_object_object_add(
-                                               json_pim_neighbors,
-                                               neigh_src_str,
-                                               json_pim_neighbor);
-                               }
-
-                               json_object_object_add(json_row, "neighbors",
-                                                      json_pim_neighbors);
-                       }
-
-                       json_object_string_add(json_row, "drAddress", dr_str);
-                       json_object_int_add(json_row, "drPriority",
-                                           pim_ifp->pim_dr_priority);
-                       json_object_string_add(json_row, "drUptime", dr_uptime);
-                       json_object_int_add(json_row, "drElections",
-                                           pim_ifp->pim_dr_election_count);
-                       json_object_int_add(json_row, "drChanges",
-                                           pim_ifp->pim_dr_election_changes);
-
-                       // FHR
-                       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
-                               if (ifp != up->rpf.source_nexthop.interface)
-                                       continue;
-
-                               if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
-                                       continue;
-
-                               if (!json_fhr_sources)
-                                       json_fhr_sources =
-                                               json_object_new_object();
-
-                               snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
-                                          &up->sg.grp);
-                               snprintfrr(src_str, sizeof(src_str), "%pPAs",
-                                          &up->sg.src);
-                               pim_time_uptime(uptime, sizeof(uptime),
-                                               now - up->state_transition);
-
-                               /*
-                                * Does this group live in json_fhr_sources?
-                                * If not create it.
-                                */
-                               json_object_object_get_ex(json_fhr_sources,
-                                                         grp_str, &json_group);
-
-                               if (!json_group) {
-                                       json_group = json_object_new_object();
-                                       json_object_object_add(json_fhr_sources,
-                                                              grp_str,
-                                                              json_group);
-                               }
-
-                               json_group_source = json_object_new_object();
-                               json_object_string_add(json_group_source,
-                                                      "source", src_str);
-                               json_object_string_add(json_group_source,
-                                                      "group", grp_str);
-                               json_object_string_add(json_group_source,
-                                                      "upTime", uptime);
-                               json_object_object_add(json_group, src_str,
-                                                      json_group_source);
-                       }
-
-                       if (json_fhr_sources) {
-                               json_object_object_add(json_row,
-                                                      "firstHopRouter",
-                                                      json_fhr_sources);
-                       }
-
-                       json_object_int_add(json_row, "helloPeriod",
-                                           pim_ifp->pim_hello_period);
-                       json_object_int_add(json_row, "holdTime",
-                                           PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
-                       json_object_string_add(json_row, "helloTimer",
-                                              hello_timer);
-                       json_object_string_add(json_row, "helloStatStart",
-                                              stat_uptime);
-                       json_object_int_add(json_row, "helloReceived",
-                                           pim_ifp->pim_ifstat_hello_recv);
-                       json_object_int_add(json_row, "helloReceivedFailed",
-                                           pim_ifp->pim_ifstat_hello_recvfail);
-                       json_object_int_add(json_row, "helloSend",
-                                           pim_ifp->pim_ifstat_hello_sent);
-                       json_object_int_add(json_row, "hellosendFailed",
-                                           pim_ifp->pim_ifstat_hello_sendfail);
-                       json_object_int_add(json_row, "helloGenerationId",
-                                           pim_ifp->pim_generation_id);
-
-                       json_object_int_add(
-                               json_row, "effectivePropagationDelay",
-                               pim_if_effective_propagation_delay_msec(ifp));
-                       json_object_int_add(
-                               json_row, "effectiveOverrideInterval",
-                               pim_if_effective_override_interval_msec(ifp));
-                       json_object_int_add(
-                               json_row, "joinPruneOverrideInterval",
-                               pim_if_jp_override_interval_msec(ifp));
-
-                       json_object_int_add(
-                               json_row, "propagationDelay",
-                               pim_ifp->pim_propagation_delay_msec);
-                       json_object_int_add(
-                               json_row, "propagationDelayHighest",
-                               pim_ifp->pim_neighbors_highest_propagation_delay_msec);
-                       json_object_int_add(
-                               json_row, "overrideInterval",
-                               pim_ifp->pim_override_interval_msec);
-                       json_object_int_add(
-                               json_row, "overrideIntervalHighest",
-                               pim_ifp->pim_neighbors_highest_override_interval_msec);
-                       if (pim_ifp->bsm_enable)
-                               json_object_boolean_true_add(json_row,
-                                                            "bsmEnabled");
-                       if (pim_ifp->ucast_bsm_accept)
-                               json_object_boolean_true_add(json_row,
-                                                            "ucastBsmEnabled");
-                       json_object_object_add(json, ifp->name, json_row);
-
-               } else {
-                       vty_out(vty, "Interface  : %s\n", ifp->name);
-                       vty_out(vty, "State      : %s\n",
-                               if_is_up(ifp) ? "up" : "down");
-                       if (pim_ifp->update_source.s_addr != INADDR_ANY) {
-                               vty_out(vty, "Use Source : %pI4\n",
-                                       &pim_ifp->update_source);
-                       }
-                       if (pim_ifp->sec_addr_list) {
-                               vty_out(vty, "Address    : %pI4 (primary)\n",
-                                       &ifaddr);
-                               for (ALL_LIST_ELEMENTS_RO(
-                                            pim_ifp->sec_addr_list, sec_node,
-                                            sec_addr))
-                                       vty_out(vty, "             %pFX\n",
-                                               &sec_addr->addr);
-                       } else {
-                               vty_out(vty, "Address    : %pI4\n",
-                                       &ifaddr);
-                       }
-                       vty_out(vty, "\n");
-
-                       // PIM neighbors
-                       print_header = 1;
-
-                       for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
-                                                 neighnode, neigh)) {
-
-                               if (print_header) {
-                                       vty_out(vty, "PIM Neighbors\n");
-                                       vty_out(vty, "-------------\n");
-                                       print_header = 0;
-                               }
-
-                               pim_inet4_dump("<src?>", neigh->source_addr,
-                                              neigh_src_str,
-                                              sizeof(neigh_src_str));
-                               pim_time_uptime(uptime, sizeof(uptime),
-                                               now - neigh->creation);
-                               pim_time_timer_to_hhmmss(expire, sizeof(expire),
-                                                        neigh->t_expire_timer);
-                               vty_out(vty,
-                                       "%-15s : up for %s, holdtime expires in %s\n",
-                                       neigh_src_str, uptime, expire);
-                       }
-
-                       if (!print_header) {
-                               vty_out(vty, "\n");
-                               vty_out(vty, "\n");
-                       }
-
-                       vty_out(vty, "Designated Router\n");
-                       vty_out(vty, "-----------------\n");
-                       vty_out(vty, "Address   : %s\n", dr_str);
-                       vty_out(vty, "Priority  : %u(%d)\n",
-                               pim_ifp->pim_dr_priority,
-                               pim_ifp->pim_dr_num_nondrpri_neighbors);
-                       vty_out(vty, "Uptime    : %s\n", dr_uptime);
-                       vty_out(vty, "Elections : %d\n",
-                               pim_ifp->pim_dr_election_count);
-                       vty_out(vty, "Changes   : %d\n",
-                               pim_ifp->pim_dr_election_changes);
-                       vty_out(vty, "\n");
-                       vty_out(vty, "\n");
-
-                       // FHR
-                       print_header = 1;
-                       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
-                               if (!up->rpf.source_nexthop.interface)
-                                       continue;
-
-                               if (strcmp(ifp->name,
-                                          up->rpf.source_nexthop
-                                          .interface->name)
-                                   != 0)
-                                       continue;
-
-                               if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
-                                       continue;
-
-                               if (print_header) {
-                                       vty_out(vty,
-                                               "FHR - First Hop Router\n");
-                                       vty_out(vty,
-                                               "----------------------\n");
-                                       print_header = 0;
-                               }
-
-                               pim_time_uptime(uptime, sizeof(uptime),
-                                               now - up->state_transition);
-                               vty_out(vty,
-                                       "%pPAs : %pPAs is a source, uptime is %s\n",
-                                       &up->sg.grp, &up->sg.src, uptime);
-                       }
-
-                       if (!print_header) {
-                               vty_out(vty, "\n");
-                               vty_out(vty, "\n");
-                       }
-
-                       vty_out(vty, "Hellos\n");
-                       vty_out(vty, "------\n");
-                       vty_out(vty, "Period         : %d\n",
-                               pim_ifp->pim_hello_period);
-                       vty_out(vty, "HoldTime       : %d\n",
-                               PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
-                       vty_out(vty, "Timer          : %s\n", hello_timer);
-                       vty_out(vty, "StatStart      : %s\n", stat_uptime);
-                       vty_out(vty, "Receive        : %d\n",
-                               pim_ifp->pim_ifstat_hello_recv);
-                       vty_out(vty, "Receive Failed : %d\n",
-                               pim_ifp->pim_ifstat_hello_recvfail);
-                       vty_out(vty, "Send           : %d\n",
-                               pim_ifp->pim_ifstat_hello_sent);
-                       vty_out(vty, "Send Failed    : %d\n",
-                               pim_ifp->pim_ifstat_hello_sendfail);
-                       vty_out(vty, "Generation ID  : %08x\n",
-                               pim_ifp->pim_generation_id);
-                       vty_out(vty, "\n");
-                       vty_out(vty, "\n");
-
-                       pim_print_ifp_flags(vty, ifp);
-
-                       vty_out(vty, "Join Prune Interval\n");
-                       vty_out(vty, "-------------------\n");
-                       vty_out(vty, "LAN Delay                    : %s\n",
-                               pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
-                       vty_out(vty, "Effective Propagation Delay  : %d msec\n",
-                               pim_if_effective_propagation_delay_msec(ifp));
-                       vty_out(vty, "Effective Override Interval  : %d msec\n",
-                               pim_if_effective_override_interval_msec(ifp));
-                       vty_out(vty, "Join Prune Override Interval : %d msec\n",
-                               pim_if_jp_override_interval_msec(ifp));
-                       vty_out(vty, "\n");
-                       vty_out(vty, "\n");
-
-                       vty_out(vty, "LAN Prune Delay\n");
-                       vty_out(vty, "---------------\n");
-                       vty_out(vty, "Propagation Delay           : %d msec\n",
-                               pim_ifp->pim_propagation_delay_msec);
-                       vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
-                               pim_ifp->pim_neighbors_highest_propagation_delay_msec);
-                       vty_out(vty, "Override Interval           : %d msec\n",
-                               pim_ifp->pim_override_interval_msec);
-                       vty_out(vty, "Override Interval (Highest) : %d msec\n",
-                               pim_ifp->pim_neighbors_highest_override_interval_msec);
-                       vty_out(vty, "\n");
-                       vty_out(vty, "\n");
-
-                       vty_out(vty, "BSM Status\n");
-                       vty_out(vty, "----------\n");
-                       vty_out(vty, "Bsm Enabled          : %s\n",
-                               pim_ifp->bsm_enable ? "yes" : "no");
-                       vty_out(vty, "Unicast Bsm Enabled  : %s\n",
-                               pim_ifp->ucast_bsm_accept ? "yes" : "no");
-                       vty_out(vty, "\n");
-                       vty_out(vty, "\n");
-               }
-       }
-
-       if (uj)
-               vty_json(vty, json);
-       else if (!found_ifname)
-               vty_out(vty, "%% No such interface\n");
-}
-
 static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
                                 const char *ifname, bool uj)
 {
@@ -1416,619 +836,28 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
        }
 }
 
-static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
-                               bool mlag, bool uj)
-{
-       struct interface *ifp;
-       struct pim_interface *pim_ifp;
-       struct pim_upstream *up;
-       int fhr = 0;
-       int pim_nbrs = 0;
-       int pim_ifchannels = 0;
-       json_object *json = NULL;
-       json_object *json_row = NULL;
-       json_object *json_tmp;
-
-       json = json_object_new_object();
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               pim_ifp = ifp->info;
-
-               if (!pim_ifp)
-                       continue;
-
-               if (mlag == true && pim_ifp->activeactive == false)
-                       continue;
-
-               pim_nbrs = pim_ifp->pim_neighbor_list->count;
-               pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
-               fhr = 0;
-
-               frr_each (rb_pim_upstream, &pim->upstream_head, up)
-                       if (ifp == up->rpf.source_nexthop.interface)
-                               if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
-                                       fhr++;
-
-               json_row = json_object_new_object();
-               json_object_pim_ifp_add(json_row, ifp);
-               json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
-               json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
-               json_object_int_add(json_row, "firstHopRouterCount", fhr);
-               json_object_string_addf(json_row, "pimDesignatedRouter", "%pI4",
-                                       &pim_ifp->pim_dr_addr);
-
-               if (pim_ifp->pim_dr_addr.s_addr
-                   == pim_ifp->primary_address.s_addr)
-                       json_object_boolean_true_add(
-                               json_row, "pimDesignatedRouterLocal");
-
-               json_object_object_add(json, ifp->name, json_row);
-       }
-
-       if (uj) {
-               vty_out(vty, "%s\n", json_object_to_json_string_ext(
-                               json, JSON_C_TO_STRING_PRETTY));
-       } else {
-               vty_out(vty,
-                       "Interface         State          Address  PIM Nbrs           PIM DR  FHR IfChannels\n");
-
-               json_object_object_foreach(json, key, val)
-               {
-                       vty_out(vty, "%-16s  ", key);
-
-                       json_object_object_get_ex(val, "state", &json_tmp);
-                       vty_out(vty, "%5s  ", json_object_get_string(json_tmp));
-
-                       json_object_object_get_ex(val, "address", &json_tmp);
-                       vty_out(vty, "%15s  ",
-                               json_object_get_string(json_tmp));
-
-                       json_object_object_get_ex(val, "pimNeighbors",
-                                                 &json_tmp);
-                       vty_out(vty, "%8d  ", json_object_get_int(json_tmp));
-
-                       if (json_object_object_get_ex(
-                                   val, "pimDesignatedRouterLocal",
-                                   &json_tmp)) {
-                               vty_out(vty, "%15s  ", "local");
-                       } else {
-                               json_object_object_get_ex(
-                                       val, "pimDesignatedRouter", &json_tmp);
-                               vty_out(vty, "%15s  ",
-                                       json_object_get_string(json_tmp));
-                       }
-
-                       json_object_object_get_ex(val, "firstHopRouter",
-                                                 &json_tmp);
-                       vty_out(vty, "%3d  ", json_object_get_int(json_tmp));
-
-                       json_object_object_get_ex(val, "pimIfChannels",
-                                                 &json_tmp);
-                       vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
-               }
-       }
-
-       json_object_free(json);
-}
-
-static void pim_show_interface_traffic(struct pim_instance *pim,
-                                      struct vty *vty, bool uj)
-{
-       struct interface *ifp = NULL;
-       struct pim_interface *pim_ifp = NULL;
-       json_object *json = NULL;
-       json_object *json_row = NULL;
-
-       if (uj)
-               json = json_object_new_object();
-       else {
-               vty_out(vty, "\n");
-               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
-                       "Interface", "       HELLO", "       JOIN",
-                       "      PRUNE", "   REGISTER", "REGISTER-STOP",
-                       "  ASSERT", "  BSM");
-               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
-                       "       Rx/Tx", "       Rx/Tx", "      Rx/Tx",
-                       "      Rx/Tx", "     Rx/Tx", "    Rx/Tx",
-                       "   Rx/Tx");
-               vty_out(vty,
-                       "---------------------------------------------------------------------------------------------------------------\n");
-       }
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               pim_ifp = ifp->info;
-
-               if (!pim_ifp)
-                       continue;
-
-               if (pim_ifp->pim_sock_fd < 0)
-                       continue;
-               if (uj) {
-                       json_row = json_object_new_object();
-                       json_object_pim_ifp_add(json_row, ifp);
-                       json_object_int_add(json_row, "helloRx",
-                                           pim_ifp->pim_ifstat_hello_recv);
-                       json_object_int_add(json_row, "helloTx",
-                                           pim_ifp->pim_ifstat_hello_sent);
-                       json_object_int_add(json_row, "joinRx",
-                                           pim_ifp->pim_ifstat_join_recv);
-                       json_object_int_add(json_row, "joinTx",
-                                           pim_ifp->pim_ifstat_join_send);
-                       json_object_int_add(json_row, "pruneTx",
-                                           pim_ifp->pim_ifstat_prune_send);
-                       json_object_int_add(json_row, "pruneRx",
-                                           pim_ifp->pim_ifstat_prune_recv);
-                       json_object_int_add(json_row, "registerRx",
-                                           pim_ifp->pim_ifstat_reg_recv);
-                       json_object_int_add(json_row, "registerTx",
-                                           pim_ifp->pim_ifstat_reg_recv);
-                       json_object_int_add(json_row, "registerStopRx",
-                                           pim_ifp->pim_ifstat_reg_stop_recv);
-                       json_object_int_add(json_row, "registerStopTx",
-                                           pim_ifp->pim_ifstat_reg_stop_send);
-                       json_object_int_add(json_row, "assertRx",
-                                           pim_ifp->pim_ifstat_assert_recv);
-                       json_object_int_add(json_row, "assertTx",
-                                           pim_ifp->pim_ifstat_assert_send);
-                       json_object_int_add(json_row, "bsmRx",
-                                           pim_ifp->pim_ifstat_bsm_rx);
-                       json_object_int_add(json_row, "bsmTx",
-                                           pim_ifp->pim_ifstat_bsm_tx);
-                       json_object_object_add(json, ifp->name, json_row);
-               } else {
-                       vty_out(vty,
-                               "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64 "/%-7" PRIu64 "\n",
-                               ifp->name, pim_ifp->pim_ifstat_hello_recv,
-                               pim_ifp->pim_ifstat_hello_sent,
-                               pim_ifp->pim_ifstat_join_recv,
-                               pim_ifp->pim_ifstat_join_send,
-                               pim_ifp->pim_ifstat_prune_recv,
-                               pim_ifp->pim_ifstat_prune_send,
-                               pim_ifp->pim_ifstat_reg_recv,
-                               pim_ifp->pim_ifstat_reg_send,
-                               pim_ifp->pim_ifstat_reg_stop_recv,
-                               pim_ifp->pim_ifstat_reg_stop_send,
-                               pim_ifp->pim_ifstat_assert_recv,
-                               pim_ifp->pim_ifstat_assert_send,
-                               pim_ifp->pim_ifstat_bsm_rx,
-                               pim_ifp->pim_ifstat_bsm_tx);
-               }
-       }
-       if (uj)
-               vty_json(vty, json);
-}
-
-static void pim_show_interface_traffic_single(struct pim_instance *pim,
-                                             struct vty *vty,
-                                             const char *ifname, bool uj)
-{
-       struct interface *ifp = NULL;
-       struct pim_interface *pim_ifp = NULL;
-       json_object *json = NULL;
-       json_object *json_row = NULL;
-       uint8_t found_ifname = 0;
-
-       if (uj)
-               json = json_object_new_object();
-       else {
-               vty_out(vty, "\n");
-               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
-                       "Interface", "    HELLO", "    JOIN", "   PRUNE",
-                       "   REGISTER", "  REGISTER-STOP", "  ASSERT",
-                       "    BSM");
-               vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
-                       "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
-                       "     Rx/Tx", "    Rx/Tx", "    Rx/Tx");
-               vty_out(vty,
-                       "-------------------------------------------------------------------------------------------------------------------------------\n");
-       }
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               if (strcmp(ifname, ifp->name))
-                       continue;
-
-               pim_ifp = ifp->info;
-
-               if (!pim_ifp)
-                       continue;
-
-               if (pim_ifp->pim_sock_fd < 0)
-                       continue;
-
-               found_ifname = 1;
-               if (uj) {
-                       json_row = json_object_new_object();
-                       json_object_pim_ifp_add(json_row, ifp);
-                       json_object_int_add(json_row, "helloRx",
-                                           pim_ifp->pim_ifstat_hello_recv);
-                       json_object_int_add(json_row, "helloTx",
-                                           pim_ifp->pim_ifstat_hello_sent);
-                       json_object_int_add(json_row, "joinRx",
-                                           pim_ifp->pim_ifstat_join_recv);
-                       json_object_int_add(json_row, "joinTx",
-                                           pim_ifp->pim_ifstat_join_send);
-                       json_object_int_add(json_row, "pruneRx",
-                                           pim_ifp->pim_ifstat_prune_recv);
-                       json_object_int_add(json_row, "pruneTx",
-                                           pim_ifp->pim_ifstat_prune_send);
-                       json_object_int_add(json_row, "registerRx",
-                                           pim_ifp->pim_ifstat_reg_recv);
-                       json_object_int_add(json_row, "registerTx",
-                                           pim_ifp->pim_ifstat_reg_recv);
-                       json_object_int_add(json_row, "registerStopRx",
-                                           pim_ifp->pim_ifstat_reg_stop_recv);
-                       json_object_int_add(json_row, "registerStopTx",
-                                           pim_ifp->pim_ifstat_reg_stop_send);
-                       json_object_int_add(json_row, "assertRx",
-                                           pim_ifp->pim_ifstat_assert_recv);
-                       json_object_int_add(json_row, "assertTx",
-                                           pim_ifp->pim_ifstat_assert_send);
-                       json_object_int_add(json_row, "bsmRx",
-                                           pim_ifp->pim_ifstat_bsm_rx);
-                       json_object_int_add(json_row, "bsmTx",
-                                           pim_ifp->pim_ifstat_bsm_tx);
-
-                       json_object_object_add(json, ifp->name, json_row);
-               } else {
-                       vty_out(vty,
-                               "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64 "/%-7" PRIu64 "\n",
-                               ifp->name, pim_ifp->pim_ifstat_hello_recv,
-                               pim_ifp->pim_ifstat_hello_sent,
-                               pim_ifp->pim_ifstat_join_recv,
-                               pim_ifp->pim_ifstat_join_send,
-                               pim_ifp->pim_ifstat_prune_recv,
-                               pim_ifp->pim_ifstat_prune_send,
-                               pim_ifp->pim_ifstat_reg_recv,
-                               pim_ifp->pim_ifstat_reg_send,
-                               pim_ifp->pim_ifstat_reg_stop_recv,
-                               pim_ifp->pim_ifstat_reg_stop_send,
-                               pim_ifp->pim_ifstat_assert_recv,
-                               pim_ifp->pim_ifstat_assert_send,
-                               pim_ifp->pim_ifstat_bsm_rx,
-                               pim_ifp->pim_ifstat_bsm_tx);
-               }
-       }
-       if (uj)
-               vty_json(vty, json);
-       else if (!found_ifname)
-               vty_out(vty, "%% No such interface\n");
-}
-
-static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
-                                struct pim_ifchannel *ch, json_object *json,
-                                time_t now, bool uj)
-{
-       json_object *json_iface = NULL;
-       json_object *json_row = NULL;
-       json_object *json_grp = NULL;
-       struct in_addr ifaddr;
-       char uptime[10];
-       char expire[10];
-       char prune[10];
-       char buf[PREFIX_STRLEN];
-
-       ifaddr = pim_ifp->primary_address;
-
-       pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
-       pim_time_timer_to_mmss(expire, sizeof(expire),
-                              ch->t_ifjoin_expiry_timer);
-       pim_time_timer_to_mmss(prune, sizeof(prune),
-                              ch->t_ifjoin_prune_pending_timer);
-
-       if (uj) {
-               char ch_grp_str[PIM_ADDRSTRLEN];
-               char ch_src_str[PIM_ADDRSTRLEN];
-
-               snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
-                          &ch->sg.grp);
-               snprintfrr(ch_src_str, sizeof(ch_src_str), "%pPAs",
-                          &ch->sg.src);
-
-               json_object_object_get_ex(json, ch->interface->name,
-                                         &json_iface);
-
-               if (!json_iface) {
-                       json_iface = json_object_new_object();
-                       json_object_pim_ifp_add(json_iface, ch->interface);
-                       json_object_object_add(json, ch->interface->name,
-                                              json_iface);
-               }
-
-               json_row = json_object_new_object();
-               json_object_string_add(json_row, "source", ch_src_str);
-               json_object_string_add(json_row, "group", ch_grp_str);
-               json_object_string_add(json_row, "upTime", uptime);
-               json_object_string_add(json_row, "expire", expire);
-               json_object_string_add(json_row, "prune", prune);
-               json_object_string_add(
-                       json_row, "channelJoinName",
-                       pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
-               if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
-#if CONFDATE > 20230131
-CPP_NOTICE("Remove JSON object commands with keys starting with capital")
-#endif
-                       json_object_int_add(json_row, "SGRpt", 1);
-                       json_object_int_add(json_row, "sgRpt", 1);
-               }
-               if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
-                       json_object_int_add(json_row, "protocolPim", 1);
-               if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
-                       json_object_int_add(json_row, "protocolIgmp", 1);
-               json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
-               if (!json_grp) {
-                       json_grp = json_object_new_object();
-                       json_object_object_add(json_grp, ch_src_str, json_row);
-                       json_object_object_add(json_iface, ch_grp_str,
-                                              json_grp);
-               } else
-                       json_object_object_add(json_grp, ch_src_str, json_row);
-       } else {
-               vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
-                       ch->interface->name,
-                       inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)),
-                       &ch->sg.src, &ch->sg.grp,
-                       pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
-                       uptime, expire, prune);
-       }
-}
-
-static void pim_show_join(struct pim_instance *pim, struct vty *vty,
-                         pim_sgaddr *sg, bool uj)
-{
-       struct pim_interface *pim_ifp;
-       struct pim_ifchannel *ch;
-       struct interface *ifp;
-       time_t now;
-       json_object *json = NULL;
-
-       now = pim_time_monotonic_sec();
-
-       if (uj)
-               json = json_object_new_object();
-       else
-               vty_out(vty,
-                       "Interface        Address         Source          Group           State      Uptime   Expire Prune\n");
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               pim_ifp = ifp->info;
-               if (!pim_ifp)
-                       continue;
-
-               RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
-                       if (!pim_sgaddr_match(ch->sg, *sg))
-                               continue;
-                       pim_show_join_helper(vty, pim_ifp, ch, json, now, uj);
-               } /* scan interface channels */
-       }
-
-       if (uj)
-               vty_json(vty, json);
-}
-
-static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
-                                     const char *neighbor, bool uj)
-{
-       struct listnode *neighnode;
-       struct interface *ifp;
-       struct pim_interface *pim_ifp;
-       struct pim_neighbor *neigh;
-       time_t now;
-       int found_neighbor = 0;
-       int option_address_list;
-       int option_dr_priority;
-       int option_generation_id;
-       int option_holdtime;
-       int option_lan_prune_delay;
-       int option_t_bit;
-       char uptime[10];
-       char expire[10];
-       char neigh_src_str[INET_ADDRSTRLEN];
-
-       json_object *json = NULL;
-       json_object *json_ifp = NULL;
-       json_object *json_row = NULL;
-
-       now = pim_time_monotonic_sec();
-
-       if (uj)
-               json = json_object_new_object();
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               pim_ifp = ifp->info;
-
-               if (!pim_ifp)
-                       continue;
-
-               if (pim_ifp->pim_sock_fd < 0)
-                       continue;
-
-               for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
-                                         neigh)) {
-                       pim_inet4_dump("<src?>", neigh->source_addr,
-                                      neigh_src_str, sizeof(neigh_src_str));
-
-                       /*
-                        * The user can specify either the interface name or the
-                        * PIM neighbor IP.
-                        * If this pim_ifp matches neither then skip.
-                        */
-                       if (strcmp(neighbor, "detail")
-                           && strcmp(neighbor, ifp->name)
-                           && strcmp(neighbor, neigh_src_str))
-                               continue;
-
-                       found_neighbor = 1;
-                       pim_time_uptime(uptime, sizeof(uptime),
-                                       now - neigh->creation);
-                       pim_time_timer_to_hhmmss(expire, sizeof(expire),
-                                                neigh->t_expire_timer);
-
-                       option_address_list = 0;
-                       option_dr_priority = 0;
-                       option_generation_id = 0;
-                       option_holdtime = 0;
-                       option_lan_prune_delay = 0;
-                       option_t_bit = 0;
-
-                       if (PIM_OPTION_IS_SET(neigh->hello_options,
-                                             PIM_OPTION_MASK_ADDRESS_LIST))
-                               option_address_list = 1;
-
-                       if (PIM_OPTION_IS_SET(neigh->hello_options,
-                                             PIM_OPTION_MASK_DR_PRIORITY))
-                               option_dr_priority = 1;
-
-                       if (PIM_OPTION_IS_SET(neigh->hello_options,
-                                             PIM_OPTION_MASK_GENERATION_ID))
-                               option_generation_id = 1;
-
-                       if (PIM_OPTION_IS_SET(neigh->hello_options,
-                                             PIM_OPTION_MASK_HOLDTIME))
-                               option_holdtime = 1;
-
-                       if (PIM_OPTION_IS_SET(neigh->hello_options,
-                                             PIM_OPTION_MASK_LAN_PRUNE_DELAY))
-                               option_lan_prune_delay = 1;
-
-                       if (PIM_OPTION_IS_SET(
-                                   neigh->hello_options,
-                                   PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
-                               option_t_bit = 1;
-
-                       if (uj) {
-
-                               /* Does this ifp live in json?  If not create
-                                * it. */
-                               json_object_object_get_ex(json, ifp->name,
-                                                         &json_ifp);
-
-                               if (!json_ifp) {
-                                       json_ifp = json_object_new_object();
-                                       json_object_pim_ifp_add(json_ifp, ifp);
-                                       json_object_object_add(json, ifp->name,
-                                                              json_ifp);
-                               }
-
-                               json_row = json_object_new_object();
-                               json_object_string_add(json_row, "interface",
-                                                      ifp->name);
-                               json_object_string_add(json_row, "address",
-                                                      neigh_src_str);
-                               json_object_string_add(json_row, "upTime",
-                                                      uptime);
-                               json_object_string_add(json_row, "holdtime",
-                                                      expire);
-                               json_object_int_add(json_row, "drPriority",
-                                                   neigh->dr_priority);
-                               json_object_int_add(json_row, "generationId",
-                                                   neigh->generation_id);
-
-                               if (option_address_list)
-                                       json_object_boolean_true_add(
-                                               json_row,
-                                               "helloOptionAddressList");
-
-                               if (option_dr_priority)
-                                       json_object_boolean_true_add(
-                                               json_row,
-                                               "helloOptionDrPriority");
-
-                               if (option_generation_id)
-                                       json_object_boolean_true_add(
-                                               json_row,
-                                               "helloOptionGenerationId");
-
-                               if (option_holdtime)
-                                       json_object_boolean_true_add(
-                                               json_row,
-                                               "helloOptionHoldtime");
-
-                               if (option_lan_prune_delay)
-                                       json_object_boolean_true_add(
-                                               json_row,
-                                               "helloOptionLanPruneDelay");
-
-                               if (option_t_bit)
-                                       json_object_boolean_true_add(
-                                               json_row, "helloOptionTBit");
-
-                               json_object_object_add(json_ifp, neigh_src_str,
-                                                      json_row);
-
-                       } else {
-                               vty_out(vty, "Interface : %s\n", ifp->name);
-                               vty_out(vty, "Neighbor  : %s\n", neigh_src_str);
-                               vty_out(vty,
-                                       "    Uptime                         : %s\n",
-                                       uptime);
-                               vty_out(vty,
-                                       "    Holdtime                       : %s\n",
-                                       expire);
-                               vty_out(vty,
-                                       "    DR Priority                    : %d\n",
-                                       neigh->dr_priority);
-                               vty_out(vty,
-                                       "    Generation ID                  : %08x\n",
-                                       neigh->generation_id);
-                               vty_out(vty,
-                                       "    Override Interval (msec)       : %d\n",
-                                       neigh->override_interval_msec);
-                               vty_out(vty,
-                                       "    Propagation Delay (msec)       : %d\n",
-                                       neigh->propagation_delay_msec);
-                               vty_out(vty,
-                                       "    Hello Option - Address List    : %s\n",
-                                       option_address_list ? "yes" : "no");
-                               vty_out(vty,
-                                       "    Hello Option - DR Priority     : %s\n",
-                                       option_dr_priority ? "yes" : "no");
-                               vty_out(vty,
-                                       "    Hello Option - Generation ID   : %s\n",
-                                       option_generation_id ? "yes" : "no");
-                               vty_out(vty,
-                                       "    Hello Option - Holdtime        : %s\n",
-                                       option_holdtime ? "yes" : "no");
-                               vty_out(vty,
-                                       "    Hello Option - LAN Prune Delay : %s\n",
-                                       option_lan_prune_delay ? "yes" : "no");
-                               vty_out(vty,
-                                       "    Hello Option - T-bit           : %s\n",
-                                       option_t_bit ? "yes" : "no");
-                               bfd_sess_show(vty, json_ifp,
-                                             neigh->bfd_session);
-                               vty_out(vty, "\n");
-                       }
-               }
-       }
-
-       if (uj)
-               vty_json(vty, json);
-       else if (!found_neighbor)
-               vty_out(vty, "%% No such interface or neighbor\n");
-}
-
-static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
-                              bool uj)
+static void pim_show_interface_traffic(struct pim_instance *pim,
+                                      struct vty *vty, bool uj)
 {
-       struct listnode *neighnode;
-       struct interface *ifp;
-       struct pim_interface *pim_ifp;
-       struct pim_neighbor *neigh;
-       time_t now;
-       char uptime[10];
-       char expire[10];
-       char neigh_src_str[INET_ADDRSTRLEN];
+       struct interface *ifp = NULL;
+       struct pim_interface *pim_ifp = NULL;
        json_object *json = NULL;
-       json_object *json_ifp_rows = NULL;
        json_object *json_row = NULL;
 
-       now = pim_time_monotonic_sec();
-
-       if (uj) {
+       if (uj)
                json = json_object_new_object();
-       } else {
+       else {
+               vty_out(vty, "\n");
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+                       "Interface", "       HELLO", "       JOIN",
+                       "      PRUNE", "   REGISTER", "REGISTER-STOP",
+                       "  ASSERT", "  BSM");
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
+                       "       Rx/Tx", "       Rx/Tx", "      Rx/Tx",
+                       "      Rx/Tx", "     Rx/Tx", "    Rx/Tx",
+                       "   Rx/Tx");
                vty_out(vty,
-                       "Interface                Neighbor    Uptime  Holdtime  DR Pri\n");
+                       "---------------------------------------------------------------------------------------------------------------\n");
        }
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2039,143 +868,155 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
 
                if (pim_ifp->pim_sock_fd < 0)
                        continue;
-
-               if (uj)
-                       json_ifp_rows = json_object_new_object();
-
-               for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
-                                         neigh)) {
-                       pim_inet4_dump("<src?>", neigh->source_addr,
-                                      neigh_src_str, sizeof(neigh_src_str));
-                       pim_time_uptime(uptime, sizeof(uptime),
-                                       now - neigh->creation);
-                       pim_time_timer_to_hhmmss(expire, sizeof(expire),
-                                                neigh->t_expire_timer);
-
-                       if (uj) {
-                               json_row = json_object_new_object();
-                               json_object_string_add(json_row, "interface",
-                                                      ifp->name);
-                               json_object_string_add(json_row, "neighbor",
-                                                      neigh_src_str);
-                               json_object_string_add(json_row, "upTime",
-                                                      uptime);
-                               json_object_string_add(json_row, "holdTime",
-                                                      expire);
-                               json_object_int_add(json_row, "holdTimeMax",
-                                                   neigh->holdtime);
-                               json_object_int_add(json_row, "drPriority",
-                                                   neigh->dr_priority);
-                               json_object_object_add(json_ifp_rows,
-                                                      neigh_src_str, json_row);
-
-                       } else {
-                               vty_out(vty, "%-16s  %15s  %8s  %8s  %6d\n",
-                                       ifp->name, neigh_src_str, uptime,
-                                       expire, neigh->dr_priority);
-                       }
-               }
-
                if (uj) {
-                       json_object_object_add(json, ifp->name, json_ifp_rows);
-                       json_ifp_rows = NULL;
+                       json_row = json_object_new_object();
+                       json_object_pim_ifp_add(json_row, ifp);
+                       json_object_int_add(json_row, "helloRx",
+                                           pim_ifp->pim_ifstat_hello_recv);
+                       json_object_int_add(json_row, "helloTx",
+                                           pim_ifp->pim_ifstat_hello_sent);
+                       json_object_int_add(json_row, "joinRx",
+                                           pim_ifp->pim_ifstat_join_recv);
+                       json_object_int_add(json_row, "joinTx",
+                                           pim_ifp->pim_ifstat_join_send);
+                       json_object_int_add(json_row, "pruneTx",
+                                           pim_ifp->pim_ifstat_prune_send);
+                       json_object_int_add(json_row, "pruneRx",
+                                           pim_ifp->pim_ifstat_prune_recv);
+                       json_object_int_add(json_row, "registerRx",
+                                           pim_ifp->pim_ifstat_reg_recv);
+                       json_object_int_add(json_row, "registerTx",
+                                           pim_ifp->pim_ifstat_reg_recv);
+                       json_object_int_add(json_row, "registerStopRx",
+                                           pim_ifp->pim_ifstat_reg_stop_recv);
+                       json_object_int_add(json_row, "registerStopTx",
+                                           pim_ifp->pim_ifstat_reg_stop_send);
+                       json_object_int_add(json_row, "assertRx",
+                                           pim_ifp->pim_ifstat_assert_recv);
+                       json_object_int_add(json_row, "assertTx",
+                                           pim_ifp->pim_ifstat_assert_send);
+                       json_object_int_add(json_row, "bsmRx",
+                                           pim_ifp->pim_ifstat_bsm_rx);
+                       json_object_int_add(json_row, "bsmTx",
+                                           pim_ifp->pim_ifstat_bsm_tx);
+                       json_object_object_add(json, ifp->name, json_row);
+               } else {
+                       vty_out(vty,
+                               "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64 "/%-7" PRIu64 "\n",
+                               ifp->name, pim_ifp->pim_ifstat_hello_recv,
+                               pim_ifp->pim_ifstat_hello_sent,
+                               pim_ifp->pim_ifstat_join_recv,
+                               pim_ifp->pim_ifstat_join_send,
+                               pim_ifp->pim_ifstat_prune_recv,
+                               pim_ifp->pim_ifstat_prune_send,
+                               pim_ifp->pim_ifstat_reg_recv,
+                               pim_ifp->pim_ifstat_reg_send,
+                               pim_ifp->pim_ifstat_reg_stop_recv,
+                               pim_ifp->pim_ifstat_reg_stop_send,
+                               pim_ifp->pim_ifstat_assert_recv,
+                               pim_ifp->pim_ifstat_assert_send,
+                               pim_ifp->pim_ifstat_bsm_rx,
+                               pim_ifp->pim_ifstat_bsm_tx);
                }
        }
-
        if (uj)
                vty_json(vty, json);
 }
 
-static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
-                                   struct pim_interface *pim_ifp,
-                                   struct pim_ifchannel *ch, json_object *json,
-                                   bool uj)
-{
-       struct pim_upstream *up = ch->upstream;
-       json_object *json_group = NULL;
-       json_object *json_row = NULL;
-
-       if (uj) {
-               char grp_str[PIM_ADDRSTRLEN];
-               char src_str[PIM_ADDRSTRLEN];
-
-               snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
-               snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src);
-
-               json_object_object_get_ex(json, grp_str, &json_group);
-
-               if (!json_group) {
-                       json_group = json_object_new_object();
-                       json_object_object_add(json, grp_str, json_group);
-               }
-
-               json_row = json_object_new_object();
-               json_object_pim_upstream_add(json_row, up);
-               json_object_string_add(json_row, "interface",
-                                      ch->interface->name);
-               json_object_string_add(json_row, "source", src_str);
-               json_object_string_add(json_row, "group", grp_str);
-
-               if (pim_macro_ch_lost_assert(ch))
-                       json_object_boolean_true_add(json_row, "lostAssert");
-
-               if (pim_macro_chisin_joins(ch))
-                       json_object_boolean_true_add(json_row, "joins");
-
-               if (pim_macro_chisin_pim_include(ch))
-                       json_object_boolean_true_add(json_row, "pimInclude");
-
-               if (pim_upstream_evaluate_join_desired(pim, up))
-                       json_object_boolean_true_add(json_row,
-                                                    "evaluateJoinDesired");
-
-               json_object_object_add(json_group, src_str, json_row);
-
-       } else {
-               vty_out(vty, "%-16s %-15pPAs %-15pPAs %-10s %-5s %-10s %-11s %-6s\n",
-                       ch->interface->name, &up->sg.src, &up->sg.grp,
-                       pim_macro_ch_lost_assert(ch) ? "yes" : "no",
-                       pim_macro_chisin_joins(ch) ? "yes" : "no",
-                       pim_macro_chisin_pim_include(ch) ? "yes" : "no",
-                       PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
-                       ? "yes"
-                       : "no",
-                       pim_upstream_evaluate_join_desired(pim, up) ? "yes"
-                       : "no");
-       }
-}
-
-static void pim_show_channel(struct pim_instance *pim, struct vty *vty,
-                            bool uj)
+static void pim_show_interface_traffic_single(struct pim_instance *pim,
+                                             struct vty *vty,
+                                             const char *ifname, bool uj)
 {
-       struct pim_interface *pim_ifp;
-       struct pim_ifchannel *ch;
-       struct interface *ifp;
-
+       struct interface *ifp = NULL;
+       struct pim_interface *pim_ifp = NULL;
        json_object *json = NULL;
+       json_object *json_row = NULL;
+       uint8_t found_ifname = 0;
 
        if (uj)
                json = json_object_new_object();
-       else
+       else {
+               vty_out(vty, "\n");
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+                       "Interface", "    HELLO", "    JOIN", "   PRUNE",
+                       "   REGISTER", "  REGISTER-STOP", "  ASSERT",
+                       "    BSM");
+               vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
+                       "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
+                       "     Rx/Tx", "    Rx/Tx", "    Rx/Tx");
                vty_out(vty,
-                       "Interface        Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD\n");
+                       "-------------------------------------------------------------------------------------------------------------------------------\n");
+       }
 
-       /* scan per-interface (S,G) state */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               if (strcmp(ifname, ifp->name))
+                       continue;
+
                pim_ifp = ifp->info;
+
                if (!pim_ifp)
                        continue;
 
+               if (pim_ifp->pim_sock_fd < 0)
+                       continue;
 
-               RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
-                       /* scan all interfaces */
-                       pim_show_channel_helper(pim, vty, pim_ifp, ch,
-                                               json, uj);
+               found_ifname = 1;
+               if (uj) {
+                       json_row = json_object_new_object();
+                       json_object_pim_ifp_add(json_row, ifp);
+                       json_object_int_add(json_row, "helloRx",
+                                           pim_ifp->pim_ifstat_hello_recv);
+                       json_object_int_add(json_row, "helloTx",
+                                           pim_ifp->pim_ifstat_hello_sent);
+                       json_object_int_add(json_row, "joinRx",
+                                           pim_ifp->pim_ifstat_join_recv);
+                       json_object_int_add(json_row, "joinTx",
+                                           pim_ifp->pim_ifstat_join_send);
+                       json_object_int_add(json_row, "pruneRx",
+                                           pim_ifp->pim_ifstat_prune_recv);
+                       json_object_int_add(json_row, "pruneTx",
+                                           pim_ifp->pim_ifstat_prune_send);
+                       json_object_int_add(json_row, "registerRx",
+                                           pim_ifp->pim_ifstat_reg_recv);
+                       json_object_int_add(json_row, "registerTx",
+                                           pim_ifp->pim_ifstat_reg_recv);
+                       json_object_int_add(json_row, "registerStopRx",
+                                           pim_ifp->pim_ifstat_reg_stop_recv);
+                       json_object_int_add(json_row, "registerStopTx",
+                                           pim_ifp->pim_ifstat_reg_stop_send);
+                       json_object_int_add(json_row, "assertRx",
+                                           pim_ifp->pim_ifstat_assert_recv);
+                       json_object_int_add(json_row, "assertTx",
+                                           pim_ifp->pim_ifstat_assert_send);
+                       json_object_int_add(json_row, "bsmRx",
+                                           pim_ifp->pim_ifstat_bsm_rx);
+                       json_object_int_add(json_row, "bsmTx",
+                                           pim_ifp->pim_ifstat_bsm_tx);
+
+                       json_object_object_add(json, ifp->name, json_row);
+               } else {
+                       vty_out(vty,
+                               "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64 "/%-7" PRIu64 "\n",
+                               ifp->name, pim_ifp->pim_ifstat_hello_recv,
+                               pim_ifp->pim_ifstat_hello_sent,
+                               pim_ifp->pim_ifstat_join_recv,
+                               pim_ifp->pim_ifstat_join_send,
+                               pim_ifp->pim_ifstat_prune_recv,
+                               pim_ifp->pim_ifstat_prune_send,
+                               pim_ifp->pim_ifstat_reg_recv,
+                               pim_ifp->pim_ifstat_reg_send,
+                               pim_ifp->pim_ifstat_reg_stop_recv,
+                               pim_ifp->pim_ifstat_reg_stop_send,
+                               pim_ifp->pim_ifstat_assert_recv,
+                               pim_ifp->pim_ifstat_assert_send,
+                               pim_ifp->pim_ifstat_bsm_rx,
+                               pim_ifp->pim_ifstat_bsm_tx);
                }
        }
-
        if (uj)
                vty_json(vty, json);
+       else if (!found_ifname)
+               vty_out(vty, "%% No such interface\n");
 }
 
 static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
@@ -2201,50 +1042,6 @@ static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
                uptime_mroute_del, (long long)pim->mroute_del_events);
 }
 
-struct pnc_cache_walk_data {
-       struct vty *vty;
-       struct pim_instance *pim;
-};
-
-static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
-{
-       struct pim_nexthop_cache *pnc = bucket->data;
-       struct pnc_cache_walk_data *cwd = arg;
-       struct vty *vty = cwd->vty;
-       struct pim_instance *pim = cwd->pim;
-       struct nexthop *nh_node = NULL;
-       ifindex_t first_ifindex;
-       struct interface *ifp = NULL;
-       char buf[PREFIX_STRLEN];
-
-       for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
-               first_ifindex = nh_node->ifindex;
-               ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
-
-               vty_out(vty, "%-15s ", inet_ntop(AF_INET,
-                                                &pnc->rpf.rpf_addr.u.prefix4,
-                                                buf, sizeof(buf)));
-               vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
-               vty_out(vty, "%pI4 ", &nh_node->gate.ipv4);
-               vty_out(vty, "\n");
-       }
-       return CMD_SUCCESS;
-}
-
-static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
-{
-       struct pnc_cache_walk_data cwd;
-
-       cwd.vty = vty;
-       cwd.pim = pim;
-       vty_out(vty, "Number of registered addresses: %lu\n",
-               pim->rpf_hash->count);
-       vty_out(vty, "Address         Interface        Nexthop\n");
-       vty_out(vty, "---------------------------------------------\n");
-
-       hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
-}
-
 /* Display the bsm database details */
 static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
 {
@@ -3857,55 +2654,6 @@ DEFUN (show_ip_pim_join_vrf_all,
        return CMD_WARNING;
 }
 
-static void pim_show_jp_agg_helper(struct vty *vty,
-                                  struct interface *ifp,
-                                  struct pim_neighbor *neigh,
-                                  struct pim_upstream *up,
-                                  int is_join)
-{
-       char rpf_str[INET_ADDRSTRLEN];
-
-       /* pius->address.s_addr */
-       pim_inet4_dump("<rpf?>", neigh->source_addr, rpf_str, sizeof(rpf_str));
-
-       vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %5s\n", ifp->name, rpf_str,
-               &up->sg.src, &up->sg.grp, is_join ? "J" : "P");
-}
-
-static void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
-{
-       struct interface *ifp;
-       struct pim_interface *pim_ifp;
-       struct listnode *n_node;
-       struct pim_neighbor *neigh;
-       struct listnode *jag_node;
-       struct pim_jp_agg_group *jag;
-       struct listnode *js_node;
-       struct pim_jp_sources *js;
-
-       vty_out(vty,
-               "Interface        RPF Nbr         Source          Group           State\n");
-
-       FOR_ALL_INTERFACES (pim->vrf, ifp) {
-               pim_ifp = ifp->info;
-               if (!pim_ifp)
-                       continue;
-
-               for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
-                                         n_node, neigh)) {
-                       for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
-                                                 jag_node, jag)) {
-                               for (ALL_LIST_ELEMENTS_RO(jag->sources,
-                                                         js_node, js)) {
-                                       pim_show_jp_agg_helper(vty,
-                                                              ifp, neigh, js->up,
-                                                              js->is_join);
-                               }
-                       }
-               }
-       }
-}
-
 DEFPY (show_ip_pim_jp_agg,
        show_ip_pim_jp_agg_cmd,
        "show ip pim [vrf NAME] jp-agg",
@@ -6471,22 +5219,6 @@ DEFUN (no_ip_pim_ssm_prefix_list_name,
        return CMD_WARNING_CONFIG_FAILED;
 }
 
-static void ip_pim_ssm_show_group_range(struct pim_instance *pim,
-                                       struct vty *vty, bool uj)
-{
-       struct pim_ssm *ssm = pim->ssm_info;
-       const char *range_str =
-               ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
-
-       if (uj) {
-               json_object *json;
-               json = json_object_new_object();
-               json_object_string_add(json, "ssmGroups", range_str);
-               vty_json(vty, json);
-       } else
-               vty_out(vty, "SSM group range : %s\n", range_str);
-}
-
 DEFUN (show_ip_pim_ssm_range,
        show_ip_pim_ssm_range_cmd,
        "show ip pim [vrf NAME] group-type [json]",
index 11b253d1eaaabcf23da7063c44c9125c910aa5fb..baea9da4e0970b973baf721866ddcba6c4fc7965 100644 (file)
 #include "vrf.h"
 #include "ferr.h"
 #include "lib/srcdest_table.h"
+#include "lib/linklist.h"
 
 #include "pimd.h"
 #include "pim_vty.h"
 #include "lib/northbound_cli.h"
 #include "pim_errors.h"
 #include "pim_nb.h"
-#include "pim_cmd_common.h"
 #include "pim_mroute.h"
 #include "pim_cmd.h"
 #include "pim6_cmd.h"
 #include "pim_zebra.h"
 #include "pim_zlookup.h"
 #include "pim_iface.h"
-#include "lib/linklist.h"
+#include "pim_macro.h"
 #include "pim_neighbor.h"
+#include "pim_nht.h"
+#include "pim_sock.h"
+#include "pim_ssm.h"
 
 /**
  * Get current node VRF name.
@@ -672,6 +675,55 @@ bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
                !pim_addr_cmp(match.src, item.src));
 }
 
+void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
+{
+       struct pim_interface *pim_ifp;
+
+       pim_ifp = ifp->info;
+       json_object_string_add(json, "name", ifp->name);
+       json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
+       json_object_string_addf(json, "address", "%pPA",
+                               &pim_ifp->primary_address);
+       json_object_int_add(json, "index", ifp->ifindex);
+
+       if (if_is_multicast(ifp))
+               json_object_boolean_true_add(json, "flagMulticast");
+
+       if (if_is_broadcast(ifp))
+               json_object_boolean_true_add(json, "flagBroadcast");
+
+       if (ifp->flags & IFF_ALLMULTI)
+               json_object_boolean_true_add(json, "flagAllMulticast");
+
+       if (ifp->flags & IFF_PROMISC)
+               json_object_boolean_true_add(json, "flagPromiscuous");
+
+       if (PIM_IF_IS_DELETED(ifp))
+               json_object_boolean_true_add(json, "flagDeleted");
+
+       if (pim_if_lan_delay_enabled(ifp))
+               json_object_boolean_true_add(json, "lanDelayEnabled");
+}
+
+void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
+{
+       vty_out(vty, "Flags\n");
+       vty_out(vty, "-----\n");
+       vty_out(vty, "All Multicast   : %s\n",
+               (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
+       vty_out(vty, "Broadcast       : %s\n",
+               if_is_broadcast(ifp) ? "yes" : "no");
+       vty_out(vty, "Deleted         : %s\n",
+               PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
+       vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
+       vty_out(vty, "Multicast       : %s\n",
+               if_is_multicast(ifp) ? "yes" : "no");
+       vty_out(vty, "Promiscuous     : %s\n",
+               (ifp->flags & IFF_PROMISC) ? "yes" : "no");
+       vty_out(vty, "\n");
+       vty_out(vty, "\n");
+}
+
 void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
 {
        json_object_boolean_add(
@@ -1521,3 +1573,1216 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
        if (uj)
                vty_json(vty, json);
 }
+
+static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
+                                struct pim_ifchannel *ch, json_object *json,
+                                time_t now, bool uj)
+{
+       json_object *json_iface = NULL;
+       json_object *json_row = NULL;
+       json_object *json_grp = NULL;
+       pim_addr ifaddr;
+       char uptime[10];
+       char expire[10];
+       char prune[10];
+       char buf[PREFIX_STRLEN];
+
+       ifaddr = pim_ifp->primary_address;
+
+       pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
+       pim_time_timer_to_mmss(expire, sizeof(expire),
+                              ch->t_ifjoin_expiry_timer);
+       pim_time_timer_to_mmss(prune, sizeof(prune),
+                              ch->t_ifjoin_prune_pending_timer);
+
+       if (uj) {
+               char ch_grp_str[PIM_ADDRSTRLEN];
+               char ch_src_str[PIM_ADDRSTRLEN];
+
+               snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
+                          &ch->sg.grp);
+               snprintfrr(ch_src_str, sizeof(ch_src_str), "%pPAs",
+                          &ch->sg.src);
+
+               json_object_object_get_ex(json, ch->interface->name,
+                                         &json_iface);
+
+               if (!json_iface) {
+                       json_iface = json_object_new_object();
+                       json_object_pim_ifp_add(json_iface, ch->interface);
+                       json_object_object_add(json, ch->interface->name,
+                                              json_iface);
+               }
+
+               json_row = json_object_new_object();
+               json_object_string_add(json_row, "source", ch_src_str);
+               json_object_string_add(json_row, "group", ch_grp_str);
+               json_object_string_add(json_row, "upTime", uptime);
+               json_object_string_add(json_row, "expire", expire);
+               json_object_string_add(json_row, "prune", prune);
+               json_object_string_add(
+                       json_row, "channelJoinName",
+                       pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
+               if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
+#if CONFDATE > 20230131
+                       CPP_NOTICE(
+                               "Remove JSON object commands with keys starting with capital")
+#endif
+                       json_object_int_add(json_row, "SGRpt", 1);
+                       json_object_int_add(json_row, "sgRpt", 1);
+               }
+               if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
+                       json_object_int_add(json_row, "protocolPim", 1);
+               if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
+                       json_object_int_add(json_row, "protocolIgmp", 1);
+               json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
+               if (!json_grp) {
+                       json_grp = json_object_new_object();
+                       json_object_object_add(json_grp, ch_src_str, json_row);
+                       json_object_object_add(json_iface, ch_grp_str,
+                                              json_grp);
+               } else
+                       json_object_object_add(json_grp, ch_src_str, json_row);
+       } else {
+               vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
+                       ch->interface->name,
+                       inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)),
+                       &ch->sg.src, &ch->sg.grp,
+                       pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
+                       uptime, expire, prune);
+       }
+}
+
+void pim_show_join(struct pim_instance *pim, struct vty *vty,
+                         pim_sgaddr *sg, bool uj)
+{
+       struct pim_interface *pim_ifp;
+       struct pim_ifchannel *ch;
+       struct interface *ifp;
+       time_t now;
+       json_object *json = NULL;
+
+       now = pim_time_monotonic_sec();
+
+       if (uj)
+               json = json_object_new_object();
+       else
+               vty_out(vty,
+                       "Interface        Address         Source          Group           State      Uptime   Expire Prune\n");
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               pim_ifp = ifp->info;
+               if (!pim_ifp)
+                       continue;
+
+               RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+                       if (!pim_sgaddr_match(ch->sg, *sg))
+                               continue;
+                       pim_show_join_helper(vty, pim_ifp, ch, json, now, uj);
+               } /* scan interface channels */
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
+
+static void pim_show_jp_agg_helper(struct vty *vty, struct interface *ifp,
+                                  struct pim_neighbor *neigh,
+                                  struct pim_upstream *up, int is_join)
+{
+       char src_str[INET_ADDRSTRLEN];
+       char grp_str[INET_ADDRSTRLEN];
+       char rpf_str[INET_ADDRSTRLEN];
+
+       pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
+       pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
+       /* pius->address.s_addr */
+       pim_inet4_dump("<rpf?>", neigh->source_addr, rpf_str, sizeof(rpf_str));
+
+       vty_out(vty, "%-16s %-15s %-15s %-15s %5s\n", ifp->name, rpf_str,
+               src_str, grp_str, is_join ? "J" : "P");
+}
+
+void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
+{
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+       struct listnode *n_node;
+       struct pim_neighbor *neigh;
+       struct listnode *jag_node;
+       struct pim_jp_agg_group *jag;
+       struct listnode *js_node;
+       struct pim_jp_sources *js;
+
+       vty_out(vty,
+               "Interface        RPF Nbr         Source          Group           State\n");
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               pim_ifp = ifp->info;
+               if (!pim_ifp)
+                       continue;
+
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, n_node,
+                                         neigh)) {
+                       for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
+                                                 jag_node, jag)) {
+                               for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
+                                                         js)) {
+                                       pim_show_jp_agg_helper(vty, ifp, neigh,
+                                                              js->up,
+                                                              js->is_join);
+                               }
+                       }
+               }
+       }
+}
+
+static void pim_show_membership_helper(struct vty *vty,
+                                      struct pim_interface *pim_ifp,
+                                      struct pim_ifchannel *ch,
+                                      struct json_object *json)
+{
+       char ch_grp_str[PIM_ADDRSTRLEN];
+       json_object *json_iface = NULL;
+       json_object *json_row = NULL;
+
+       json_object_object_get_ex(json, ch->interface->name, &json_iface);
+       if (!json_iface) {
+               json_iface = json_object_new_object();
+               json_object_pim_ifp_add(json_iface, ch->interface);
+               json_object_object_add(json, ch->interface->name, json_iface);
+       }
+
+       snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs", &ch->sg.grp);
+
+       json_row = json_object_new_object();
+       json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
+       json_object_string_add(json_row, "group", ch_grp_str);
+       json_object_string_add(json_row, "localMembership",
+                              ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
+                                          ? "NOINFO"
+                                          : "INCLUDE");
+       json_object_object_add(json_iface, ch_grp_str, json_row);
+}
+
+void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+       struct pim_interface *pim_ifp;
+       struct pim_ifchannel *ch;
+       struct interface *ifp;
+       enum json_type type;
+       json_object *json = NULL;
+       json_object *json_tmp = NULL;
+
+       json = json_object_new_object();
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               pim_ifp = ifp->info;
+               if (!pim_ifp)
+                       continue;
+
+               RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+                       pim_show_membership_helper(vty, pim_ifp, ch, json);
+               } /* scan interface channels */
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                               json, JSON_C_TO_STRING_PRETTY));
+       } else {
+               vty_out(vty,
+                       "Interface         Address          Source           Group            Membership\n");
+
+               /*
+                * Example of the json data we are traversing
+                *
+                * {
+                *   "swp3":{
+                *     "name":"swp3",
+                *     "state":"up",
+                *     "address":"10.1.20.1",
+                *     "index":5,
+                *     "flagMulticast":true,
+                *     "flagBroadcast":true,
+                *     "lanDelayEnabled":true,
+                *     "226.10.10.10":{
+                *       "source":"*",
+                *       "group":"226.10.10.10",
+                *       "localMembership":"INCLUDE"
+                *     }
+                *   }
+                * }
+                */
+
+               /* foreach interface */
+               json_object_object_foreach(json, key, val)
+               {
+
+                       /* Find all of the keys where the val is an object. In
+                        * the example
+                        * above the only one is 226.10.10.10
+                        */
+                       json_object_object_foreach(val, if_field_key,
+                                                  if_field_val)
+                       {
+                               type = json_object_get_type(if_field_val);
+
+                               if (type == json_type_object) {
+                                       vty_out(vty, "%-16s  ", key);
+
+                                       json_object_object_get_ex(
+                                               val, "address", &json_tmp);
+                                       vty_out(vty, "%-15s  ",
+                                               json_object_get_string(
+                                                       json_tmp));
+
+                                       json_object_object_get_ex(if_field_val,
+                                                                 "source",
+                                                                 &json_tmp);
+                                       vty_out(vty, "%-15s  ",
+                                               json_object_get_string(
+                                                       json_tmp));
+
+                                       /* Group */
+                                       vty_out(vty, "%-15s  ", if_field_key);
+
+                                       json_object_object_get_ex(
+                                               if_field_val, "localMembership",
+                                               &json_tmp);
+                                       vty_out(vty, "%-10s\n",
+                                               json_object_get_string(
+                                                       json_tmp));
+                               }
+                       }
+               }
+       }
+
+       json_object_free(json);
+}
+
+static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
+                                   struct pim_interface *pim_ifp,
+                                   struct pim_ifchannel *ch, json_object *json,
+                                   bool uj)
+{
+       struct pim_upstream *up = ch->upstream;
+       json_object *json_group = NULL;
+       char src_str[INET_ADDRSTRLEN];
+       char grp_str[INET_ADDRSTRLEN];
+       json_object *json_row = NULL;
+
+       pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
+       pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
+
+       if (uj) {
+               json_object_object_get_ex(json, grp_str, &json_group);
+
+               if (!json_group) {
+                       json_group = json_object_new_object();
+                       json_object_object_add(json, grp_str, json_group);
+               }
+
+               json_row = json_object_new_object();
+               json_object_pim_upstream_add(json_row, up);
+               json_object_string_add(json_row, "interface",
+                                      ch->interface->name);
+               json_object_string_add(json_row, "source", src_str);
+               json_object_string_add(json_row, "group", grp_str);
+
+               if (pim_macro_ch_lost_assert(ch))
+                       json_object_boolean_true_add(json_row, "lostAssert");
+
+               if (pim_macro_chisin_joins(ch))
+                       json_object_boolean_true_add(json_row, "joins");
+
+               if (pim_macro_chisin_pim_include(ch))
+                       json_object_boolean_true_add(json_row, "pimInclude");
+
+               if (pim_upstream_evaluate_join_desired(pim, up))
+                       json_object_boolean_true_add(json_row,
+                                                    "evaluateJoinDesired");
+
+               json_object_object_add(json_group, src_str, json_row);
+
+       } else {
+               vty_out(vty, "%-16s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
+                       ch->interface->name, src_str, grp_str,
+                       pim_macro_ch_lost_assert(ch) ? "yes" : "no",
+                       pim_macro_chisin_joins(ch) ? "yes" : "no",
+                       pim_macro_chisin_pim_include(ch) ? "yes" : "no",
+                       PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
+                               ? "yes"
+                               : "no",
+                       pim_upstream_evaluate_join_desired(pim, up) ? "yes"
+                                                                   : "no");
+       }
+}
+
+void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+       struct pim_interface *pim_ifp;
+       struct pim_ifchannel *ch;
+       struct interface *ifp;
+
+       json_object *json = NULL;
+
+       if (uj)
+               json = json_object_new_object();
+       else
+               vty_out(vty,
+                       "Interface        Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD\n");
+
+       /* scan per-interface (S,G) state */
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               pim_ifp = ifp->info;
+               if (!pim_ifp)
+                       continue;
+
+
+               RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+                       /* scan all interfaces */
+                       pim_show_channel_helper(pim, vty, pim_ifp, ch, json,
+                                               uj);
+               }
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
+
+void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
+                        bool uj)
+{
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+       struct pim_upstream *up;
+       int fhr = 0;
+       int pim_nbrs = 0;
+       int pim_ifchannels = 0;
+       json_object *json = NULL;
+       json_object *json_row = NULL;
+       json_object *json_tmp;
+
+       json = json_object_new_object();
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               pim_ifp = ifp->info;
+
+               if (!pim_ifp)
+                       continue;
+
+               if (mlag == true && pim_ifp->activeactive == false)
+                       continue;
+
+               pim_nbrs = pim_ifp->pim_neighbor_list->count;
+               pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
+               fhr = 0;
+
+               frr_each (rb_pim_upstream, &pim->upstream_head, up)
+                       if (ifp == up->rpf.source_nexthop.interface)
+                               if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
+                                       fhr++;
+
+               json_row = json_object_new_object();
+               json_object_pim_ifp_add(json_row, ifp);
+               json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
+               json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
+               json_object_int_add(json_row, "firstHopRouterCount", fhr);
+               json_object_string_addf(json_row, "pimDesignatedRouter", "%pPAs",
+                                       &pim_ifp->pim_dr_addr);
+
+               if (pim_addr_cmp(pim_ifp->pim_dr_addr,
+                       pim_ifp->primary_address))
+                       json_object_boolean_true_add(
+                               json_row, "pimDesignatedRouterLocal");
+
+               json_object_object_add(json, ifp->name, json_row);
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n",
+                       json_object_to_json_string_ext(
+                               json, JSON_C_TO_STRING_PRETTY));
+       } else {
+               vty_out(vty,
+                       "Interface         State          Address  PIM Nbrs           PIM DR  FHR IfChannels\n");
+
+               json_object_object_foreach(json, key, val)
+               {
+                       vty_out(vty, "%-16s  ", key);
+
+                       json_object_object_get_ex(val, "state", &json_tmp);
+                       vty_out(vty, "%5s  ", json_object_get_string(json_tmp));
+
+                       json_object_object_get_ex(val, "address", &json_tmp);
+                       vty_out(vty, "%15s  ",
+                               json_object_get_string(json_tmp));
+
+                       json_object_object_get_ex(val, "pimNeighbors",
+                                                 &json_tmp);
+                       vty_out(vty, "%8d  ", json_object_get_int(json_tmp));
+
+                       if (json_object_object_get_ex(
+                                   val, "pimDesignatedRouterLocal",
+                                   &json_tmp)) {
+                               vty_out(vty, "%15s  ", "local");
+                       } else {
+                               json_object_object_get_ex(
+                                       val, "pimDesignatedRouter", &json_tmp);
+                               vty_out(vty, "%15s  ",
+                                       json_object_get_string(json_tmp));
+                       }
+
+                       json_object_object_get_ex(val, "firstHopRouter",
+                                                 &json_tmp);
+                       vty_out(vty, "%3d  ", json_object_get_int(json_tmp));
+
+                       json_object_object_get_ex(val, "pimIfChannels",
+                                                 &json_tmp);
+                       vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
+               }
+       }
+
+       json_object_free(json);
+}
+
+void pim_show_interfaces_single(struct pim_instance *pim,
+                               struct vty *vty, const char *ifname,
+                               bool mlag, bool uj)
+{
+       pim_addr ifaddr;
+       struct interface *ifp;
+       struct listnode *neighnode;
+       struct pim_interface *pim_ifp;
+       struct pim_neighbor *neigh;
+       struct pim_upstream *up;
+       time_t now;
+       char dr_str[INET_ADDRSTRLEN];
+       char dr_uptime[10];
+       char expire[10];
+       char grp_str[INET_ADDRSTRLEN];
+       char hello_period[10];
+       char hello_timer[10];
+       char neigh_src_str[INET_ADDRSTRLEN];
+       char src_str[INET_ADDRSTRLEN];
+       char stat_uptime[10];
+       char uptime[10];
+       int found_ifname = 0;
+       int print_header;
+       json_object *json = NULL;
+       json_object *json_row = NULL;
+       json_object *json_pim_neighbor = NULL;
+       json_object *json_pim_neighbors = NULL;
+       json_object *json_group = NULL;
+       json_object *json_group_source = NULL;
+       json_object *json_fhr_sources = NULL;
+       struct pim_secondary_addr *sec_addr;
+       struct listnode *sec_node;
+
+       now = pim_time_monotonic_sec();
+
+       if (uj)
+               json = json_object_new_object();
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               pim_ifp = ifp->info;
+
+               if (!pim_ifp)
+                       continue;
+
+               if (mlag == true && pim_ifp->activeactive == false)
+                       continue;
+
+               if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
+                       continue;
+
+               found_ifname = 1;
+               ifaddr = pim_ifp->primary_address;
+               pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str,
+                              sizeof(dr_str));
+               pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
+                                     pim_ifp->pim_dr_election_last);
+               pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
+                                        pim_ifp->t_pim_hello_timer);
+               pim_time_mmss(hello_period, sizeof(hello_period),
+                             pim_ifp->pim_hello_period);
+               pim_time_uptime(stat_uptime, sizeof(stat_uptime),
+                               now - pim_ifp->pim_ifstat_start);
+
+               if (uj) {
+                       char pbuf[PREFIX2STR_BUFFER];
+
+                       json_row = json_object_new_object();
+                       json_object_pim_ifp_add(json_row, ifp);
+
+                       if (pim_ifp->update_source.s_addr != INADDR_ANY) {
+                               json_object_string_addf(
+                                       json_row, "useSource", "%pI4",
+                                       &pim_ifp->update_source);
+                       }
+                       if (pim_ifp->sec_addr_list) {
+                               json_object *sec_list = NULL;
+
+                               sec_list = json_object_new_array();
+                               for (ALL_LIST_ELEMENTS_RO(
+                                            pim_ifp->sec_addr_list, sec_node,
+                                            sec_addr)) {
+                                       json_object_array_add(
+                                               sec_list,
+                                               json_object_new_string(
+                                                       prefix2str(
+                                                               &sec_addr->addr,
+                                                               pbuf,
+                                                               sizeof(pbuf))));
+                               }
+                               json_object_object_add(json_row,
+                                                      "secondaryAddressList",
+                                                      sec_list);
+                       }
+
+                       /* PIM neighbors */
+                       if (pim_ifp->pim_neighbor_list->count) {
+                               json_pim_neighbors = json_object_new_object();
+
+                               for (ALL_LIST_ELEMENTS_RO(
+                                            pim_ifp->pim_neighbor_list,
+                                            neighnode, neigh)) {
+                                       json_pim_neighbor =
+                                               json_object_new_object();
+                                       pim_inet4_dump("<src?>",
+                                                      neigh->source_addr,
+                                                      neigh_src_str,
+                                                      sizeof(neigh_src_str));
+                                       pim_time_uptime(uptime, sizeof(uptime),
+                                                       now - neigh->creation);
+                                       pim_time_timer_to_hhmmss(
+                                               expire, sizeof(expire),
+                                               neigh->t_expire_timer);
+
+                                       json_object_string_add(
+                                               json_pim_neighbor, "address",
+                                               neigh_src_str);
+                                       json_object_string_add(
+                                               json_pim_neighbor, "upTime",
+                                               uptime);
+                                       json_object_string_add(
+                                               json_pim_neighbor, "holdtime",
+                                               expire);
+
+                                       json_object_object_add(
+                                               json_pim_neighbors,
+                                               neigh_src_str,
+                                               json_pim_neighbor);
+                               }
+
+                               json_object_object_add(json_row, "neighbors",
+                                                      json_pim_neighbors);
+                       }
+
+                       json_object_string_add(json_row, "drAddress", dr_str);
+                       json_object_int_add(json_row, "drPriority",
+                                           pim_ifp->pim_dr_priority);
+                       json_object_string_add(json_row, "drUptime", dr_uptime);
+                       json_object_int_add(json_row, "drElections",
+                                           pim_ifp->pim_dr_election_count);
+                       json_object_int_add(json_row, "drChanges",
+                                           pim_ifp->pim_dr_election_changes);
+
+                       /* FHR */
+                       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+                               if (ifp != up->rpf.source_nexthop.interface)
+                                       continue;
+
+                               if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
+                                       continue;
+
+                               if (!json_fhr_sources)
+                                       json_fhr_sources =
+                                               json_object_new_object();
+
+                               snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
+                                          &up->sg.grp);
+                               snprintfrr(src_str, sizeof(src_str), "%pPAs",
+                                          &up->sg.src);
+                               pim_time_uptime(uptime, sizeof(uptime),
+                                               now - up->state_transition);
+
+                               /*
+                                * Does this group live in json_fhr_sources?
+                                * If not create it.
+                                */
+                               json_object_object_get_ex(json_fhr_sources,
+                                                         grp_str, &json_group);
+
+                               if (!json_group) {
+                                       json_group = json_object_new_object();
+                                       json_object_object_add(json_fhr_sources,
+                                                              grp_str,
+                                                              json_group);
+                               }
+
+                               json_group_source = json_object_new_object();
+                               json_object_string_add(json_group_source,
+                                                      "source", src_str);
+                               json_object_string_add(json_group_source,
+                                                      "group", grp_str);
+                               json_object_string_add(json_group_source,
+                                                      "upTime", uptime);
+                               json_object_object_add(json_group, src_str,
+                                                      json_group_source);
+                       }
+
+                       if (json_fhr_sources) {
+                               json_object_object_add(json_row,
+                                                      "firstHopRouter",
+                                                      json_fhr_sources);
+                       }
+
+                       json_object_int_add(json_row, "helloPeriod",
+                                           pim_ifp->pim_hello_period);
+                       json_object_int_add(json_row, "holdTime",
+                                           PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
+                       json_object_string_add(json_row, "helloTimer",
+                                              hello_timer);
+                       json_object_string_add(json_row, "helloStatStart",
+                                              stat_uptime);
+                       json_object_int_add(json_row, "helloReceived",
+                                           pim_ifp->pim_ifstat_hello_recv);
+                       json_object_int_add(json_row, "helloReceivedFailed",
+                                           pim_ifp->pim_ifstat_hello_recvfail);
+                       json_object_int_add(json_row, "helloSend",
+                                           pim_ifp->pim_ifstat_hello_sent);
+                       json_object_int_add(json_row, "hellosendFailed",
+                                           pim_ifp->pim_ifstat_hello_sendfail);
+                       json_object_int_add(json_row, "helloGenerationId",
+                                           pim_ifp->pim_generation_id);
+
+                       json_object_int_add(
+                               json_row, "effectivePropagationDelay",
+                               pim_if_effective_propagation_delay_msec(ifp));
+                       json_object_int_add(
+                               json_row, "effectiveOverrideInterval",
+                               pim_if_effective_override_interval_msec(ifp));
+                       json_object_int_add(
+                               json_row, "joinPruneOverrideInterval",
+                               pim_if_jp_override_interval_msec(ifp));
+
+                       json_object_int_add(
+                               json_row, "propagationDelay",
+                               pim_ifp->pim_propagation_delay_msec);
+                       json_object_int_add(
+                               json_row, "propagationDelayHighest",
+                               pim_ifp->pim_neighbors_highest_propagation_delay_msec);
+                       json_object_int_add(
+                               json_row, "overrideInterval",
+                               pim_ifp->pim_override_interval_msec);
+                       json_object_int_add(
+                               json_row, "overrideIntervalHighest",
+                               pim_ifp->pim_neighbors_highest_override_interval_msec);
+                       if (pim_ifp->bsm_enable)
+                               json_object_boolean_true_add(json_row,
+                                                            "bsmEnabled");
+                       if (pim_ifp->ucast_bsm_accept)
+                               json_object_boolean_true_add(json_row,
+                                                            "ucastBsmEnabled");
+                       json_object_object_add(json, ifp->name, json_row);
+
+               } else {
+                       vty_out(vty, "Interface  : %s\n", ifp->name);
+                       vty_out(vty, "State      : %s\n",
+                               if_is_up(ifp) ? "up" : "down");
+                       if (pim_ifp->update_source.s_addr != INADDR_ANY) {
+                               vty_out(vty, "Use Source : %pI4\n",
+                                       &pim_ifp->update_source);
+                       }
+                       if (pim_ifp->sec_addr_list) {
+                               vty_out(vty, "Address    : %pI4 (primary)\n",
+                                       &ifaddr);
+                               for (ALL_LIST_ELEMENTS_RO(
+                                            pim_ifp->sec_addr_list, sec_node,
+                                            sec_addr))
+                                       vty_out(vty, "             %pFX\n",
+                                               &sec_addr->addr);
+                       } else {
+                               vty_out(vty, "Address    : %pI4\n",
+                                       &ifaddr);
+                       }
+                       vty_out(vty, "\n");
+
+                       /* PIM neighbors */
+                       print_header = 1;
+
+                       for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
+                                                 neighnode, neigh)) {
+
+                               if (print_header) {
+                                       vty_out(vty, "PIM Neighbors\n");
+                                       vty_out(vty, "-------------\n");
+                                       print_header = 0;
+                               }
+
+                               pim_inet4_dump("<src?>", neigh->source_addr,
+                                              neigh_src_str,
+                                              sizeof(neigh_src_str));
+                               pim_time_uptime(uptime, sizeof(uptime),
+                                               now - neigh->creation);
+                               pim_time_timer_to_hhmmss(expire, sizeof(expire),
+                                                        neigh->t_expire_timer);
+                               vty_out(vty,
+                                       "%-15s : up for %s, holdtime expires in %s\n",
+                                       neigh_src_str, uptime, expire);
+                       }
+
+                       if (!print_header) {
+                               vty_out(vty, "\n");
+                               vty_out(vty, "\n");
+                       }
+
+                       vty_out(vty, "Designated Router\n");
+                       vty_out(vty, "-----------------\n");
+                       vty_out(vty, "Address   : %s\n", dr_str);
+                       vty_out(vty, "Priority  : %u(%d)\n",
+                               pim_ifp->pim_dr_priority,
+                               pim_ifp->pim_dr_num_nondrpri_neighbors);
+                       vty_out(vty, "Uptime    : %s\n", dr_uptime);
+                       vty_out(vty, "Elections : %d\n",
+                               pim_ifp->pim_dr_election_count);
+                       vty_out(vty, "Changes   : %d\n",
+                               pim_ifp->pim_dr_election_changes);
+                       vty_out(vty, "\n");
+                       vty_out(vty, "\n");
+
+                       /* FHR */
+                       print_header = 1;
+                       frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+                               if (!up->rpf.source_nexthop.interface)
+                                       continue;
+
+                               if (strcmp(ifp->name,
+                                          up->rpf.source_nexthop
+                                          .interface->name) != 0)
+                                       continue;
+
+                               if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
+                                       continue;
+
+                               if (print_header) {
+                                       vty_out(vty,
+                                               "FHR - First Hop Router\n");
+                                       vty_out(vty,
+                                               "----------------------\n");
+                                       print_header = 0;
+                               }
+
+                               pim_time_uptime(uptime, sizeof(uptime),
+                                               now - up->state_transition);
+                               vty_out(vty,
+                                       "%pPAs : %pPAs is a source, uptime is %s\n",
+                                       &up->sg.grp, &up->sg.src, uptime);
+                       }
+
+                       if (!print_header) {
+                               vty_out(vty, "\n");
+                               vty_out(vty, "\n");
+                       }
+
+                       vty_out(vty, "Hellos\n");
+                       vty_out(vty, "------\n");
+                       vty_out(vty, "Period         : %d\n",
+                               pim_ifp->pim_hello_period);
+                       vty_out(vty, "HoldTime       : %d\n",
+                               PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
+                       vty_out(vty, "Timer          : %s\n", hello_timer);
+                       vty_out(vty, "StatStart      : %s\n", stat_uptime);
+                       vty_out(vty, "Receive        : %d\n",
+                               pim_ifp->pim_ifstat_hello_recv);
+                       vty_out(vty, "Receive Failed : %d\n",
+                               pim_ifp->pim_ifstat_hello_recvfail);
+                       vty_out(vty, "Send           : %d\n",
+                               pim_ifp->pim_ifstat_hello_sent);
+                       vty_out(vty, "Send Failed    : %d\n",
+                               pim_ifp->pim_ifstat_hello_sendfail);
+                       vty_out(vty, "Generation ID  : %08x\n",
+                               pim_ifp->pim_generation_id);
+                       vty_out(vty, "\n");
+                       vty_out(vty, "\n");
+
+                       pim_print_ifp_flags(vty, ifp);
+
+                       vty_out(vty, "Join Prune Interval\n");
+                       vty_out(vty, "-------------------\n");
+                       vty_out(vty, "LAN Delay                    : %s\n",
+                               pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
+                       vty_out(vty, "Effective Propagation Delay  : %d msec\n",
+                               pim_if_effective_propagation_delay_msec(ifp));
+                       vty_out(vty, "Effective Override Interval  : %d msec\n",
+                               pim_if_effective_override_interval_msec(ifp));
+                       vty_out(vty, "Join Prune Override Interval : %d msec\n",
+                               pim_if_jp_override_interval_msec(ifp));
+                       vty_out(vty, "\n");
+                       vty_out(vty, "\n");
+
+                       vty_out(vty, "LAN Prune Delay\n");
+                       vty_out(vty, "---------------\n");
+                       vty_out(vty, "Propagation Delay           : %d msec\n",
+                               pim_ifp->pim_propagation_delay_msec);
+                       vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
+                               pim_ifp->pim_neighbors_highest_propagation_delay_msec);
+                       vty_out(vty, "Override Interval           : %d msec\n",
+                               pim_ifp->pim_override_interval_msec);
+                       vty_out(vty, "Override Interval (Highest) : %d msec\n",
+                               pim_ifp->pim_neighbors_highest_override_interval_msec);
+                       vty_out(vty, "\n");
+                       vty_out(vty, "\n");
+
+                       vty_out(vty, "BSM Status\n");
+                       vty_out(vty, "----------\n");
+                       vty_out(vty, "Bsm Enabled          : %s\n",
+                               pim_ifp->bsm_enable ? "yes" : "no");
+                       vty_out(vty, "Unicast Bsm Enabled  : %s\n",
+                               pim_ifp->ucast_bsm_accept ? "yes" : "no");
+                       vty_out(vty, "\n");
+                       vty_out(vty, "\n");
+               }
+       }
+
+       if (uj)
+               vty_json(vty, json);
+       else if (!found_ifname)
+               vty_out(vty, "%% No such interface\n");
+}
+
+void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
+                                bool uj)
+{
+       struct pim_ssm *ssm = pim->ssm_info;
+       const char *range_str =
+               ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
+
+       if (uj) {
+               json_object *json;
+
+               json = json_object_new_object();
+               json_object_string_add(json, "ssmGroups", range_str);
+               vty_json(vty, json);
+       } else
+               vty_out(vty, "SSM group range : %s\n", range_str);
+}
+
+struct pnc_cache_walk_data {
+       struct vty *vty;
+       struct pim_instance *pim;
+};
+
+static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
+{
+       struct pim_nexthop_cache *pnc = bucket->data;
+       struct pnc_cache_walk_data *cwd = arg;
+       struct vty *vty = cwd->vty;
+       struct pim_instance *pim = cwd->pim;
+       struct nexthop *nh_node = NULL;
+       ifindex_t first_ifindex;
+       struct interface *ifp = NULL;
+       char buf[PREFIX_STRLEN];
+
+       for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
+               first_ifindex = nh_node->ifindex;
+               ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
+
+               vty_out(vty, "%-15s ",
+                       inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, buf,
+                                 sizeof(buf)));
+               vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
+               vty_out(vty, "%pI4 ", &nh_node->gate.ipv4);
+               vty_out(vty, "\n");
+       }
+       return CMD_SUCCESS;
+}
+
+void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
+{
+       struct pnc_cache_walk_data cwd;
+
+       cwd.vty = vty;
+       cwd.pim = pim;
+       vty_out(vty, "Number of registered addresses: %lu\n",
+               pim->rpf_hash->count);
+       vty_out(vty, "Address         Interface        Nexthop\n");
+       vty_out(vty, "---------------------------------------------\n");
+
+       hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
+}
+
+void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
+                              const char *neighbor, json_object *json)
+{
+       struct listnode *neighnode;
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+       struct pim_neighbor *neigh;
+       time_t now;
+       int found_neighbor = 0;
+       int option_address_list;
+       int option_dr_priority;
+       int option_generation_id;
+       int option_holdtime;
+       int option_lan_prune_delay;
+       int option_t_bit;
+       char uptime[10];
+       char expire[10];
+       char neigh_src_str[PIM_ADDRSTRLEN];
+
+       json_object *json_ifp = NULL;
+       json_object *json_row = NULL;
+
+       now = pim_time_monotonic_sec();
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               pim_ifp = ifp->info;
+
+               if (!pim_ifp)
+                       continue;
+
+               if (pim_ifp->pim_sock_fd < 0)
+                       continue;
+
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
+                                         neigh)) {
+                       snprintfrr(neigh_src_str, sizeof(neigh_src_str),
+                                  "%pPAs", &neigh->source_addr);
+
+                       /*
+                        * The user can specify either the interface name or the
+                        * PIM neighbor IP.
+                        * If this pim_ifp matches neither then skip.
+                        */
+                       if (strcmp(neighbor, "detail") &&
+                           strcmp(neighbor, ifp->name) &&
+                           strcmp(neighbor, neigh_src_str))
+                               continue;
+
+                       found_neighbor = 1;
+                       pim_time_uptime(uptime, sizeof(uptime),
+                                       now - neigh->creation);
+                       pim_time_timer_to_hhmmss(expire, sizeof(expire),
+                                                neigh->t_expire_timer);
+
+                       option_address_list = 0;
+                       option_dr_priority = 0;
+                       option_generation_id = 0;
+                       option_holdtime = 0;
+                       option_lan_prune_delay = 0;
+                       option_t_bit = 0;
+
+                       if (PIM_OPTION_IS_SET(neigh->hello_options,
+                                             PIM_OPTION_MASK_ADDRESS_LIST))
+                               option_address_list = 1;
+
+                       if (PIM_OPTION_IS_SET(neigh->hello_options,
+                                             PIM_OPTION_MASK_DR_PRIORITY))
+                               option_dr_priority = 1;
+
+                       if (PIM_OPTION_IS_SET(neigh->hello_options,
+                                             PIM_OPTION_MASK_GENERATION_ID))
+                               option_generation_id = 1;
+
+                       if (PIM_OPTION_IS_SET(neigh->hello_options,
+                                             PIM_OPTION_MASK_HOLDTIME))
+                               option_holdtime = 1;
+
+                       if (PIM_OPTION_IS_SET(neigh->hello_options,
+                                             PIM_OPTION_MASK_LAN_PRUNE_DELAY))
+                               option_lan_prune_delay = 1;
+
+                       if (PIM_OPTION_IS_SET(
+                                   neigh->hello_options,
+                                   PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
+                               option_t_bit = 1;
+
+                       if (json) {
+
+                               /* Does this ifp live in json? If not create it
+                                */
+                               json_object_object_get_ex(json, ifp->name,
+                                                         &json_ifp);
+
+                               if (!json_ifp) {
+                                       json_ifp = json_object_new_object();
+                                       json_object_pim_ifp_add(json_ifp, ifp);
+                                       json_object_object_add(json, ifp->name,
+                                                              json_ifp);
+                               }
+
+                               json_row = json_object_new_object();
+                               json_object_string_add(json_row, "interface",
+                                                      ifp->name);
+                               json_object_string_add(json_row, "address",
+                                                      neigh_src_str);
+                               json_object_string_add(json_row, "upTime",
+                                                      uptime);
+                               json_object_string_add(json_row, "holdtime",
+                                                      expire);
+                               json_object_int_add(json_row, "drPriority",
+                                                   neigh->dr_priority);
+                               json_object_int_add(json_row, "generationId",
+                                                   neigh->generation_id);
+
+                               if (option_address_list)
+                                       json_object_boolean_true_add(
+                                               json_row,
+                                               "helloOptionAddressList");
+
+                               if (option_dr_priority)
+                                       json_object_boolean_true_add(
+                                               json_row,
+                                               "helloOptionDrPriority");
+
+                               if (option_generation_id)
+                                       json_object_boolean_true_add(
+                                               json_row,
+                                               "helloOptionGenerationId");
+
+                               if (option_holdtime)
+                                       json_object_boolean_true_add(
+                                               json_row,
+                                               "helloOptionHoldtime");
+
+                               if (option_lan_prune_delay)
+                                       json_object_boolean_true_add(
+                                               json_row,
+                                               "helloOptionLanPruneDelay");
+
+                               if (option_t_bit)
+                                       json_object_boolean_true_add(
+                                               json_row, "helloOptionTBit");
+
+                               json_object_object_add(json_ifp, neigh_src_str,
+                                                      json_row);
+
+                       } else {
+                               vty_out(vty, "Interface : %s\n", ifp->name);
+                               vty_out(vty, "Neighbor  : %s\n", neigh_src_str);
+                               vty_out(vty,
+                                       "    Uptime                         : %s\n",
+                                       uptime);
+                               vty_out(vty,
+                                       "    Holdtime                       : %s\n",
+                                       expire);
+                               vty_out(vty,
+                                       "    DR Priority                    : %d\n",
+                                       neigh->dr_priority);
+                               vty_out(vty,
+                                       "    Generation ID                  : %08x\n",
+                                       neigh->generation_id);
+                               vty_out(vty,
+                                       "    Override Interval (msec)       : %d\n",
+                                       neigh->override_interval_msec);
+                               vty_out(vty,
+                                       "    Propagation Delay (msec)       : %d\n",
+                                       neigh->propagation_delay_msec);
+                               vty_out(vty,
+                                       "    Hello Option - Address List    : %s\n",
+                                       option_address_list ? "yes" : "no");
+                               vty_out(vty,
+                                       "    Hello Option - DR Priority     : %s\n",
+                                       option_dr_priority ? "yes" : "no");
+                               vty_out(vty,
+                                       "    Hello Option - Generation ID   : %s\n",
+                                       option_generation_id ? "yes" : "no");
+                               vty_out(vty,
+                                       "    Hello Option - Holdtime        : %s\n",
+                                       option_holdtime ? "yes" : "no");
+                               vty_out(vty,
+                                       "    Hello Option - LAN Prune Delay : %s\n",
+                                       option_lan_prune_delay ? "yes" : "no");
+                               vty_out(vty,
+                                       "    Hello Option - T-bit           : %s\n",
+                                       option_t_bit ? "yes" : "no");
+                               bfd_sess_show(vty, json_ifp,
+                                             neigh->bfd_session);
+                               vty_out(vty, "\n");
+                       }
+               }
+       }
+
+       if (!found_neighbor)
+               vty_out(vty, "%% No such interface or neighbor\n");
+}
+
+void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+       struct listnode *neighnode;
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+       struct pim_neighbor *neigh;
+       time_t now;
+       char uptime[10];
+       char expire[10];
+       char neigh_src_str[INET_ADDRSTRLEN];
+       json_object *json = NULL;
+       json_object *json_ifp_rows = NULL;
+       json_object *json_row = NULL;
+
+       now = pim_time_monotonic_sec();
+
+       if (uj) {
+               json = json_object_new_object();
+       } else {
+               vty_out(vty,
+                       "Interface                Neighbor    Uptime  Holdtime  DR Pri\n");
+       }
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               pim_ifp = ifp->info;
+
+               if (!pim_ifp)
+                       continue;
+
+               if (pim_ifp->pim_sock_fd < 0)
+                       continue;
+
+               if (uj)
+                       json_ifp_rows = json_object_new_object();
+
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
+                                         neigh)) {
+                       pim_inet4_dump("<src?>", neigh->source_addr,
+                                      neigh_src_str, sizeof(neigh_src_str));
+                       pim_time_uptime(uptime, sizeof(uptime),
+                                       now - neigh->creation);
+                       pim_time_timer_to_hhmmss(expire, sizeof(expire),
+                                                neigh->t_expire_timer);
+
+                       if (uj) {
+                               json_row = json_object_new_object();
+                               json_object_string_add(json_row, "interface",
+                                                      ifp->name);
+                               json_object_string_add(json_row, "neighbor",
+                                                      neigh_src_str);
+                               json_object_string_add(json_row, "upTime",
+                                                      uptime);
+                               json_object_string_add(json_row, "holdTime",
+                                                      expire);
+                               json_object_int_add(json_row, "holdTimeMax",
+                                                   neigh->holdtime);
+                               json_object_int_add(json_row, "drPriority",
+                                                   neigh->dr_priority);
+                               json_object_object_add(json_ifp_rows,
+                                                      neigh_src_str, json_row);
+
+                       } else {
+                               vty_out(vty, "%-16s  %15s  %8s  %8s  %6d\n",
+                                       ifp->name, neigh_src_str, uptime,
+                                       expire, neigh->dr_priority);
+                       }
+               }
+
+               if (uj) {
+                       json_object_object_add(json, ifp->name, json_ifp_rows);
+                       json_ifp_rows = NULL;
+               }
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
index 0e8955354da4e04d10ac2b4c8429e96e2e89ed84..12255a61f83e3decd1bf4712cdbe2da3a388684b 100644 (file)
@@ -73,9 +73,26 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj);
 void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
                                time_t now, json_object *json);
 bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match);
-
+void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp);
+void pim_print_ifp_flags(struct vty *vty, struct interface *ifp);
+void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up);
+void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
+                  bool uj);
+void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty);
+void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj);
+void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj);
+void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
+                        bool uj);
+void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty,
+                               const char *ifname, bool mlag, bool uj);
+void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
+                                bool uj);
+void pim_show_nexthop(struct pim_instance *pim, struct vty *vty);
+void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
+                              const char *neighbor, bool uj);
+void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, bool uj);
 /*
- * Special Macro to allow us to get the correct pim_instance;
+ * Special Macro to allow us to get the correct pim_instance
  */
 #define PIM_DECLVAR_CONTEXT(A, B)                                              \
        struct vrf *A = VTY_GET_CONTEXT(vrf);                                  \