From e2b601e8e1d0e4a6b1d8f671597e1f37a1835736 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Tue, 8 Feb 2022 09:14:26 -0800 Subject: [PATCH] pimd: Moving the common functions from pim_cmd.c file 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 --- pimd/pim_cmd.c | 1550 ++++------------------------------------- pimd/pim_cmd_common.c | 1269 ++++++++++++++++++++++++++++++++- pimd/pim_cmd_common.h | 21 +- 3 files changed, 1427 insertions(+), 1413 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 633bacadc9..67e32c8e4a 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -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("", 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("", - 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("", 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("", 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("", 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("", 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]", diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 11b253d1ea..baea9da4e0 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -31,13 +31,13 @@ #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" @@ -46,8 +46,11 @@ #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("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + /* pius->address.s_addr */ + pim_inet4_dump("", 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("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", 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("", 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("", + 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("", 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("", 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); +} diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 0e8955354d..12255a61f8 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -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); \ -- 2.39.5