From e2b601e8e1d0e4a6b1d8f671597e1f37a1835736 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Tue, 8 Feb 2022 09:14:26 -0800 Subject: [PATCH 1/8] 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 | 1268 ---------------------------------------- pimd/pim_cmd_common.c | 1269 ++++++++++++++++++++++++++++++++++++++++- pimd/pim_cmd_common.h | 21 +- 3 files changed, 1286 insertions(+), 1272 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 633bacadc..67e32c8e4 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,101 +836,6 @@ 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) { @@ -1694,490 +1019,6 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim, 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) -{ - 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); -} - -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) -{ - 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); -} - static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty, time_t now) { @@ -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 11b253d1e..baea9da4e 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 0e8955354..12255a61f 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); \ From bf083b3a66ded698345c856d26df3e11030f6e03 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Fri, 25 Feb 2022 01:47:35 -0800 Subject: [PATCH 2/8] pim6d: Adding "show ipv6 pim channel" command Adding new CLI to display pim channel informations. Changing DEFUN to DEPFY for ""show ip pim channel" Signed-off-by: Sai Gomathi N --- pimd/pim6_cmd.c | 24 ++++++++++++++++++++++++ pimd/pim_cmd.c | 15 ++++++++------- pimd/pim_cmd_common.c | 22 ++++++++++++---------- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index a6f8a3e52..d91c76984 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -1068,6 +1068,29 @@ DEFPY (show_ipv6_pim_state_vrf_all, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_channel, + show_ipv6_pim_channel_cmd, + "show ipv6 pim [vrf NAME] channel [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM downstream channel info\n" + JSON_STR) +{ + struct vrf *v; + bool uj = !!json; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + pim_show_channel(v->info, vty, uj); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1132,4 +1155,5 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_upstream_rpf_cmd); install_element(VIEW_NODE, &show_ipv6_pim_state_cmd); install_element(VIEW_NODE, &show_ipv6_pim_state_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_channel_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 67e32c8e4..28cccdd20 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3228,9 +3228,9 @@ DEFPY (show_ip_pim_upstream_vrf_all, return CMD_SUCCESS; } -DEFUN (show_ip_pim_channel, +DEFPY (show_ip_pim_channel, show_ip_pim_channel_cmd, - "show ip pim [vrf NAME] channel [json]", + "show ip pim [vrf NAME] channel [json$json]", SHOW_STR IP_STR PIM_STR @@ -3238,14 +3238,15 @@ DEFUN (show_ip_pim_channel, "PIM downstream channel info\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct vrf *v; + bool uj = !!json; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - pim_show_channel(vrf->info, vty, uj); + pim_show_channel(v->info, vty, uj); return CMD_SUCCESS; } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index baea9da4e..01cd5a1c1 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -1867,14 +1867,12 @@ static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty, { 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) { + char grp_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp); json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { @@ -1886,8 +1884,10 @@ static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty, 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); + json_object_string_addf(json_row, "source", "%pPAs", + &up->sg.src); + json_object_string_addf(json_row, "group", "%pPAs", + &up->sg.grp); if (pim_macro_ch_lost_assert(ch)) json_object_boolean_true_add(json_row, "lostAssert"); @@ -1902,11 +1902,13 @@ static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty, json_object_boolean_true_add(json_row, "evaluateJoinDesired"); - json_object_object_add(json_group, src_str, json_row); + json_object_object_addf(json_group, json_row, "%pPAs", + &up->sg.src); } else { - vty_out(vty, "%-16s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n", - ch->interface->name, src_str, grp_str, + 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", From 44f99d22320439947f31283309af512ddb205ef1 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Mon, 28 Feb 2022 02:28:14 -0800 Subject: [PATCH 3/8] pim6d: Adding "show ipv6 pim [vrf|vrf all] interface" command Adding show ipv6 pim interface and show ipv6 pim vrf all interface CLIs to display pim enabled interface informations and formatted the json output for "show ip pim interface" and "show ip pim vrf all interface" commands. Signed-off-by: Sai Gomathi N --- pimd/pim6_cmd.c | 79 ++++++++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 81 ++++++++++++++++++++------------------- pimd/pim_cmd_common.c | 89 ++++++++++++++++++------------------------- pimd/pim_cmd_common.h | 5 ++- 4 files changed, 160 insertions(+), 94 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index d91c76984..f4ac9165d 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -1091,6 +1091,83 @@ DEFPY (show_ipv6_pim_channel, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_interface, + show_ipv6_pim_interface_cmd, + "show ipv6 pim [vrf NAME] interface [detail|WORD]$interface [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM interface information\n" + "Detailed output\n" + "interface name\n" + JSON_STR) +{ + struct vrf *v; + bool uj = !!json; + json_object *json_parent = NULL; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + if (uj) + json_parent = json_object_new_object(); + + if (interface) + pim_show_interfaces_single(v->info, vty, interface, false, + json_parent); + else + pim_show_interfaces(v->info, vty, false, json_parent); + + if (uj) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_pim_interface_vrf_all, + show_ipv6_pim_interface_vrf_all_cmd, + "show ipv6 pim vrf all interface [detail|WORD]$interface [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM interface information\n" + "Detailed output\n" + "interface name\n" + JSON_STR) +{ + bool uj = !!json; + struct vrf *v; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; + + if (uj) + json_parent = json_object_new_object(); + + RB_FOREACH (v, vrf_name_head, &vrfs_by_name) { + if (!uj) + vty_out(vty, "VRF: %s\n", v->name); + else + json_vrf = json_object_new_object(); + + if (interface) + pim_show_interfaces_single(v->info, vty, interface, + false, json_vrf); + else + pim_show_interfaces(v->info, vty, false, json_vrf); + + if (uj) + json_object_object_add(json_parent, v->name, json_vrf); + } + if (uj) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1156,4 +1233,6 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_state_cmd); install_element(VIEW_NODE, &show_ipv6_pim_state_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_channel_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_interface_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_interface_vrf_all_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 28cccdd20..70c54d275 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2498,9 +2498,9 @@ DEFUN (show_ip_pim_assert_winner_metric, return CMD_SUCCESS; } -DEFUN (show_ip_pim_interface, +DEFPY (show_ip_pim_interface, show_ip_pim_interface_cmd, - "show ip pim [mlag] [vrf NAME] interface [detail|WORD] [json]", + "show ip pim [mlag$mlag] [vrf NAME] interface [detail|WORD]$interface [json$json]", SHOW_STR IP_STR PIM_STR @@ -2511,30 +2511,34 @@ DEFUN (show_ip_pim_interface, "interface name\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); - bool mlag = false; + struct vrf *v; + bool uj = !!json; + bool is_mlag = !!mlag; + json_object *json_parent = NULL; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - if (argv_find(argv, argc, "mlag", &idx)) - mlag = true; + if (uj) + json_parent = json_object_new_object(); - if (argv_find(argv, argc, "WORD", &idx) - || argv_find(argv, argc, "detail", &idx)) - pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, mlag, - uj); + if (interface) + pim_show_interfaces_single(v->info, vty, interface, is_mlag, + json_parent); else - pim_show_interfaces(vrf->info, vty, mlag, uj); + pim_show_interfaces(v->info, vty, is_mlag, json_parent); + + if (uj) + vty_json(vty, json_parent); return CMD_SUCCESS; } -DEFUN (show_ip_pim_interface_vrf_all, +DEFPY (show_ip_pim_interface_vrf_all, show_ip_pim_interface_vrf_all_cmd, - "show ip pim [mlag] vrf all interface [detail|WORD] [json]", + "show ip pim [mlag$mlag] vrf all interface [detail|WORD]$interface [json$json]", SHOW_STR IP_STR PIM_STR @@ -2545,35 +2549,32 @@ DEFUN (show_ip_pim_interface_vrf_all, "interface name\n" JSON_STR) { - int idx = 2; - bool uj = use_json(argc, argv); - struct vrf *vrf; - bool first = true; - bool mlag = false; + bool uj = !!json; + bool is_mlag = !!mlag; + struct vrf *v; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; - if (argv_find(argv, argc, "mlag", &idx)) - mlag = true; - - idx = 6; if (uj) - vty_out(vty, "{ "); - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (uj) { - if (!first) - vty_out(vty, ", "); - vty_out(vty, " \"%s\": ", vrf->name); - first = false; - } else - vty_out(vty, "VRF: %s\n", vrf->name); - if (argv_find(argv, argc, "WORD", &idx) - || argv_find(argv, argc, "detail", &idx)) - pim_show_interfaces_single(vrf->info, vty, - argv[idx]->arg, mlag, uj); + json_parent = json_object_new_object(); + + RB_FOREACH (v, vrf_name_head, &vrfs_by_name) { + if (!uj) + vty_out(vty, "VRF: %s\n", v->name); else - pim_show_interfaces(vrf->info, vty, mlag, uj); + json_vrf = json_object_new_object(); + + if (interface) + pim_show_interfaces_single(v->info, vty, interface, + is_mlag, json_vrf); + else + pim_show_interfaces(v->info, vty, is_mlag, json_vrf); + + if (uj) + json_object_object_add(json_parent, v->name, json_vrf); } if (uj) - vty_out(vty, "}\n"); + vty_json(vty, json_parent); return CMD_SUCCESS; } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 01cd5a1c1..480a1659e 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -1953,7 +1953,7 @@ 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) + json_object *json) { struct interface *ifp; struct pim_interface *pim_ifp; @@ -1961,11 +1961,14 @@ void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag, int fhr = 0; int pim_nbrs = 0; int pim_ifchannels = 0; - json_object *json = NULL; + bool uj = true; json_object *json_row = NULL; json_object *json_tmp; - json = json_object_new_object(); + if (!json) { + uj = false; + json = json_object_new_object(); + } FOR_ALL_INTERFACES (pim->vrf, ifp) { pim_ifp = ifp->info; @@ -1990,22 +1993,18 @@ void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag, 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); + 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)) + 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 { + if (!uj) { vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n"); @@ -2044,13 +2043,11 @@ void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag, 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) +void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty, + const char *ifname, bool mlag, + json_object *json) { pim_addr ifaddr; struct interface *ifp; @@ -2059,19 +2056,18 @@ void pim_show_interfaces_single(struct pim_instance *pim, struct pim_neighbor *neigh; struct pim_upstream *up; time_t now; - char dr_str[INET_ADDRSTRLEN]; + char dr_str[PIM_ADDRSTRLEN]; char dr_uptime[10]; char expire[10]; - char grp_str[INET_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; char hello_period[10]; char hello_timer[10]; - char neigh_src_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; + char neigh_src_str[PIM_ADDRSTRLEN]; + char src_str[PIM_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; @@ -2083,9 +2079,6 @@ void pim_show_interfaces_single(struct pim_instance *pim, now = pim_time_monotonic_sec(); - if (uj) - json = json_object_new_object(); - FOR_ALL_INTERFACES (pim->vrf, ifp) { pim_ifp = ifp->info; @@ -2100,8 +2093,8 @@ void pim_show_interfaces_single(struct pim_instance *pim, found_ifname = 1; ifaddr = pim_ifp->primary_address; - pim_inet4_dump("", pim_ifp->pim_dr_addr, dr_str, - sizeof(dr_str)); + snprintfrr(dr_str, sizeof(dr_str), "%pPAs", + &pim_ifp->pim_dr_addr); 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), @@ -2111,15 +2104,13 @@ void pim_show_interfaces_single(struct pim_instance *pim, pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start); - if (uj) { - char pbuf[PREFIX2STR_BUFFER]; - + if (json) { json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); - if (pim_ifp->update_source.s_addr != INADDR_ANY) { + if (!pim_addr_is_any(pim_ifp->update_source)) { json_object_string_addf( - json_row, "useSource", "%pI4", + json_row, "useSource", "%pPAs", &pim_ifp->update_source); } if (pim_ifp->sec_addr_list) { @@ -2131,11 +2122,9 @@ void pim_show_interfaces_single(struct pim_instance *pim, sec_addr)) { json_object_array_add( sec_list, - json_object_new_string( - prefix2str( - &sec_addr->addr, - pbuf, - sizeof(pbuf)))); + json_object_new_stringf( + "%pFXh", + &sec_addr->addr)); } json_object_object_add(json_row, "secondaryAddressList", @@ -2151,10 +2140,10 @@ void pim_show_interfaces_single(struct pim_instance *pim, neighnode, neigh)) { json_pim_neighbor = json_object_new_object(); - pim_inet4_dump("", - neigh->source_addr, - neigh_src_str, - sizeof(neigh_src_str)); + snprintfrr(neigh_src_str, + sizeof(neigh_src_str), + "%pPAs", + &neigh->source_addr); pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); pim_time_timer_to_hhmmss( @@ -2293,12 +2282,12 @@ void pim_show_interfaces_single(struct pim_instance *pim, 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", + if (!pim_addr_is_any(pim_ifp->update_source)) { + vty_out(vty, "Use Source : %pPAs\n", &pim_ifp->update_source); } if (pim_ifp->sec_addr_list) { - vty_out(vty, "Address : %pI4 (primary)\n", + vty_out(vty, "Address : %pPAs (primary)\n", &ifaddr); for (ALL_LIST_ELEMENTS_RO( pim_ifp->sec_addr_list, sec_node, @@ -2306,8 +2295,7 @@ void pim_show_interfaces_single(struct pim_instance *pim, vty_out(vty, " %pFX\n", &sec_addr->addr); } else { - vty_out(vty, "Address : %pI4\n", - &ifaddr); + vty_out(vty, "Address : %pPAs\n", &ifaddr); } vty_out(vty, "\n"); @@ -2323,9 +2311,8 @@ void pim_show_interfaces_single(struct pim_instance *pim, print_header = 0; } - pim_inet4_dump("", neigh->source_addr, - neigh_src_str, - sizeof(neigh_src_str)); + snprintfrr(neigh_src_str, sizeof(neigh_src_str), + "%pPAs", &neigh->source_addr); pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); pim_time_timer_to_hhmmss(expire, sizeof(expire), @@ -2362,7 +2349,7 @@ void pim_show_interfaces_single(struct pim_instance *pim, if (strcmp(ifp->name, up->rpf.source_nexthop - .interface->name) != 0) + .interface->name) != 0) continue; if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)) @@ -2448,9 +2435,7 @@ void pim_show_interfaces_single(struct pim_instance *pim, } } - if (uj) - vty_json(vty, json); - else if (!found_ifname) + if (!found_ifname) vty_out(vty, "%% No such interface\n"); } diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 12255a61f..4cf2b0ff6 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -82,9 +82,10 @@ 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); + json_object *json); void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty, - const char *ifname, bool mlag, bool uj); + const char *ifname, bool mlag, + json_object *json); 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); From 24de75a2545f23d20cd981728bddf8e810f6aea1 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Tue, 1 Mar 2022 20:50:22 -0800 Subject: [PATCH 4/8] pim6d: Adding "show ipv6 pim [vrf|vrf all] join" command Adding show ipv6 pim join and show ipv6 pim vrf all join CLIs to display pim join related information and formatted the json output for "show ip pim join" and "show ip pim vrf all join" commands. Signed-off-by: Sai Gomathi N --- pimd/pim6_cmd.c | 87 +++++++++++++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 48 ++++++++++++++---------- pimd/pim_cmd_common.c | 52 ++++++++++++-------------- pimd/pim_cmd_common.h | 2 +- 4 files changed, 139 insertions(+), 50 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index f4ac9165d..8c9b0329b 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -37,6 +37,7 @@ #include "lib/northbound_cli.h" #include "pim_errors.h" #include "pim_nb.h" +#include "pim_addr.h" #include "pim_cmd_common.h" #ifndef VTYSH_EXTRACT_PL @@ -1168,6 +1169,90 @@ DEFPY (show_ipv6_pim_interface_vrf_all, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_join, + show_ipv6_pim_join_cmd, + "show ipv6 pim [vrf NAME] join [X:X::X:X$s_or_g [X:X::X:X$g]] [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM interface join information\n" + "The Source or Group\n" + "The Group\n" + JSON_STR) +{ + pim_sgaddr sg = {}; + struct vrf *v; + struct pim_instance *pim; + json_object *json_parent = NULL; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) { + vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf); + return CMD_WARNING; + } + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + if (!pim_addr_is_any(s_or_g)) { + if (!pim_addr_is_any(g)) { + sg.src = s_or_g; + sg.grp = g; + } else + sg.grp = s_or_g; + } + + if (json) + json_parent = json_object_new_object(); + + pim_show_join(pim, vty, &sg, json_parent); + + if (json) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_pim_join_vrf_all, + show_ipv6_pim_join_vrf_all_cmd, + "show ipv6 pim vrf all join [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM interface join information\n" + JSON_STR) +{ + pim_sgaddr sg = {0}; + struct vrf *vrf_struct; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; + + if (json) + json_parent = json_object_new_object(); + + RB_FOREACH (vrf_struct, vrf_name_head, &vrfs_by_name) { + if (!json_parent) + vty_out(vty, "VRF: %s\n", vrf_struct->name); + else + json_vrf = json_object_new_object(); + pim_show_join(vrf_struct->info, vty, &sg, json_vrf); + + if (json) + json_object_object_add(json_parent, vrf_struct->name, + json_vrf); + } + if (json) + vty_json(vty, json_parent); + + return CMD_WARNING; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1235,4 +1320,6 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_channel_cmd); install_element(VIEW_NODE, &show_ipv6_pim_interface_cmd); install_element(VIEW_NODE, &show_ipv6_pim_interface_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_join_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_join_vrf_all_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 70c54d275..c064be159 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -67,6 +67,7 @@ #include "lib/northbound_cli.h" #include "pim_errors.h" #include "pim_nb.h" +#include "pim_addr.h" #include "pim_cmd_common.h" #ifndef VTYSH_EXTRACT_PL @@ -2593,8 +2594,8 @@ DEFPY (show_ip_pim_join, { pim_sgaddr sg = {0}; struct vrf *v; - bool uj = !!json; struct pim_instance *pim; + json_object *json_parent = NULL; v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); @@ -2617,14 +2618,20 @@ DEFPY (show_ip_pim_join, sg.grp = s_or_g; } - pim_show_join(pim, vty, &sg, uj); + if (json) + json_parent = json_object_new_object(); + + pim_show_join(pim, vty, &sg, json_parent); + + if (json) + vty_json(vty, json_parent); return CMD_SUCCESS; } -DEFUN (show_ip_pim_join_vrf_all, +DEFPY (show_ip_pim_join_vrf_all, show_ip_pim_join_vrf_all_cmd, - "show ip pim vrf all join [json]", + "show ip pim vrf all join [json$json]", SHOW_STR IP_STR PIM_STR @@ -2633,24 +2640,25 @@ DEFUN (show_ip_pim_join_vrf_all, JSON_STR) { pim_sgaddr sg = {0}; - bool uj = use_json(argc, argv); - struct vrf *vrf; - bool first = true; + struct vrf *vrf_struct; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; - if (uj) - vty_out(vty, "{ "); - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (uj) { - if (!first) - vty_out(vty, ", "); - vty_out(vty, " \"%s\": ", vrf->name); - first = false; - } else - vty_out(vty, "VRF: %s\n", vrf->name); - pim_show_join(vrf->info, vty, &sg, uj); + if (json) + json_parent = json_object_new_object(); + RB_FOREACH (vrf_struct, vrf_name_head, &vrfs_by_name) { + if (!json) + vty_out(vty, "VRF: %s\n", vrf_struct->name); + else + json_vrf = json_object_new_object(); + pim_show_join(vrf_struct->info, vty, &sg, json_vrf); + + if (json) + json_object_object_add(json_parent, vrf_struct->name, + json_vrf); } - if (uj) - vty_out(vty, "}\n"); + if (json) + vty_json(vty, json_parent); return CMD_WARNING; } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 480a1659e..4a92050d5 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -51,6 +51,7 @@ #include "pim_nht.h" #include "pim_sock.h" #include "pim_ssm.h" +#include "pim_addr.h" /** * Get current node VRF name. @@ -1576,7 +1577,7 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) 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) + time_t now) { json_object *json_iface = NULL; json_object *json_row = NULL; @@ -1585,7 +1586,6 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, char uptime[10]; char expire[10]; char prune[10]; - char buf[PREFIX_STRLEN]; ifaddr = pim_ifp->primary_address; @@ -1595,14 +1595,8 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, pim_time_timer_to_mmss(prune, sizeof(prune), ch->t_ifjoin_prune_pending_timer); - if (uj) { + if (json) { 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); @@ -1615,8 +1609,10 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, } 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_addf(json_row, "source", "%pPAs", + &ch->sg.src); + json_object_string_addf(json_row, "group", "%pPAs", + &ch->sg.grp); json_object_string_add(json_row, "upTime", uptime); json_object_string_add(json_row, "expire", expire); json_object_string_add(json_row, "prune", prune); @@ -1635,38 +1631,38 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, 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); + snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs", + &ch->sg.grp); 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); + json_object_object_addf(json_grp, json_row, "%pPAs", + &ch->sg.src); + json_object_object_addf(json_iface, json_grp, "%pPAs", + &ch->sg.grp); } else - json_object_object_add(json_grp, ch_src_str, json_row); + json_object_object_addf(json_grp, json_row, "%pPAs", + &ch->sg.src); } 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, + vty_out(vty, + "%-16s %-15pPAs %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n", + ch->interface->name, &ifaddr, &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) +void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg, + json_object *json) { 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 + if (!json) vty_out(vty, "Interface Address Source Group State Uptime Expire Prune\n"); @@ -1678,12 +1674,10 @@ void pim_show_join(struct pim_instance *pim, struct vty *vty, 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); + + pim_show_join_helper(vty, pim_ifp, ch, json, now); } /* scan interface channels */ } - - if (uj) - vty_json(vty, json); } static void pim_show_jp_agg_helper(struct vty *vty, struct interface *ifp, diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 4cf2b0ff6..13fd40b99 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -77,7 +77,7 @@ 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); + json_object *json); 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); From be2232396a046292c28b624899609379f720b785 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Tue, 1 Mar 2022 21:13:01 -0800 Subject: [PATCH 5/8] pim6d: Adding "show ipv6 pim jp-agg" command Adding new show CLI to display pim join prune aggregate information. Signed-off-by: Sai Gomathi N --- pimd/pim6_cmd.c | 31 +++++++++++++++++++++++++++++++ pimd/pim_cmd_common.c | 14 +++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 8c9b0329b..636999c4b 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -1253,6 +1253,36 @@ DEFPY (show_ipv6_pim_join_vrf_all, return CMD_WARNING; } +DEFPY (show_ipv6_pim_jp_agg, + show_ipv6_pim_jp_agg_cmd, + "show ipv6 pim [vrf NAME] jp-agg", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "join prune aggregation list\n") +{ + struct vrf *v; + struct pim_instance *pim; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) { + vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf); + return CMD_WARNING; + } + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + pim_show_jp_agg_list(pim, vty); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1322,4 +1352,5 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_interface_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_join_cmd); install_element(VIEW_NODE, &show_ipv6_pim_join_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_jp_agg_cmd); } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 4a92050d5..b859e4a47 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -1684,17 +1684,9 @@ 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"); + vty_out(vty, "%-16s %-15pPAs %-15pPAs %-15pPAs %5s\n", ifp->name, + &neigh->source_addr, &up->sg.src, &up->sg.grp, + is_join ? "J" : "P"); } void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty) From de11054ed02fb5b25f7b5619bd6507261d4e38f0 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Tue, 1 Mar 2022 22:15:32 -0800 Subject: [PATCH 6/8] pim6d: Adding "show ipv6 pim local-membership" Adding the new cli to display pim local membership information. Changing DEFUN to DEPFY for "show ip pim local-membership" Signed-off-by: Sai Gomathi N --- pimd/pim6_cmd.c | 24 ++++++++++++++++++++++++ pimd/pim_cmd.c | 15 ++++++++------- pimd/pim_cmd_common.c | 17 ++++++----------- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 636999c4b..a1a6d9d3f 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -1283,6 +1283,29 @@ DEFPY (show_ipv6_pim_jp_agg, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_local_membership, + show_ipv6_pim_local_membership_cmd, + "show ipv6 pim [vrf NAME] local-membership [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM interface local-membership\n" + JSON_STR) +{ + struct vrf *v; + bool uj = !!json; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + pim_show_membership(v->info, vty, uj); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1353,4 +1376,5 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_join_cmd); install_element(VIEW_NODE, &show_ipv6_pim_join_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_jp_agg_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_local_membership_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c064be159..bd7e24bd0 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2693,9 +2693,9 @@ DEFPY (show_ip_pim_jp_agg, return CMD_SUCCESS; } -DEFUN (show_ip_pim_local_membership, +DEFPY (show_ip_pim_local_membership, show_ip_pim_local_membership_cmd, - "show ip pim [vrf NAME] local-membership [json]", + "show ip pim [vrf NAME] local-membership [json$json]", SHOW_STR IP_STR PIM_STR @@ -2703,14 +2703,15 @@ DEFUN (show_ip_pim_local_membership, "PIM interface local-membership\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct vrf *v; + bool uj = !!json; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - pim_show_membership(vrf->info, vty, uj); + pim_show_membership(v->info, vty, uj); return CMD_SUCCESS; } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index b859e4a47..441a00816 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -1728,7 +1728,6 @@ static void pim_show_membership_helper(struct vty *vty, struct pim_ifchannel *ch, struct json_object *json) { - char ch_grp_str[PIM_ADDRSTRLEN]; json_object *json_iface = NULL; json_object *json_row = NULL; @@ -1739,16 +1738,14 @@ static void pim_show_membership_helper(struct vty *vty, 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_addf(json_row, "group", "%pPAs", &ch->sg.grp); 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); + ? "NOINFO" + : "INCLUDE"); + json_object_object_addf(json_iface, json_row, "%pPAs", &ch->sg.grp); } void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj) @@ -1773,8 +1770,7 @@ void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj) } if (uj) { - vty_out(vty, "%s\n", json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); + vty_json(vty, json); } else { vty_out(vty, "Interface Address Source Group Membership\n"); @@ -1841,9 +1837,8 @@ void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj) } } } + json_object_free(json); } - - json_object_free(json); } static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty, From 1295dbebe8b581e5f4337495ca6d2c728e8826d9 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Wed, 2 Mar 2022 01:22:13 -0800 Subject: [PATCH 7/8] pim6d: Adding "show ipv6 [vrf|vrf ALL] pim neighbor" command Adding new show CLI to display regarding pim neighbors. Changing DEFUN to DEFPY for "show ip pim neighbor" command. Signed-off-by: Sai Gomathi N --- pimd/pim6_cmd.c | 75 +++++++++++++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 71 +++++++++++++++++++++------------------- pimd/pim_cmd_common.c | 23 ++++++------- pimd/pim_cmd_common.h | 5 +-- 4 files changed, 125 insertions(+), 49 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index a1a6d9d3f..aa264c475 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -1306,6 +1306,79 @@ DEFPY (show_ipv6_pim_local_membership, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_neighbor, + show_ipv6_pim_neighbor_cmd, + "show ipv6 pim [vrf NAME] neighbor [detail|WORD]$interface [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM neighbor information\n" + "Detailed output\n" + "Name of interface or neighbor\n" + JSON_STR) +{ + struct vrf *v; + json_object *json_parent = NULL; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + if (json) + json_parent = json_object_new_object(); + + if (interface) + pim_show_neighbors_single(v->info, vty, interface, json_parent); + else + pim_show_neighbors(v->info, vty, json_parent); + + if (json) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_pim_neighbor_vrf_all, + show_ipv6_pim_neighbor_vrf_all_cmd, + "show ipv6 pim vrf all neighbor [detail|WORD]$interface [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM neighbor information\n" + "Detailed output\n" + "Name of interface or neighbor\n" + JSON_STR) +{ + struct vrf *v; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; + + if (json) + json_parent = json_object_new_object(); + RB_FOREACH (v, vrf_name_head, &vrfs_by_name) { + if (!json) + vty_out(vty, "VRF: %s\n", v->name); + else + json_vrf = json_object_new_object(); + + if (interface) + pim_show_neighbors_single(v->info, vty, interface, + json_vrf); + else + pim_show_neighbors(v->info, vty, json_vrf); + + if (json) + json_object_object_add(json_parent, v->name, json_vrf); + } + if (json) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1377,4 +1450,6 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_join_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_jp_agg_cmd); install_element(VIEW_NODE, &show_ipv6_pim_local_membership_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_neighbor_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_neighbor_vrf_all_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index bd7e24bd0..3b6a62d65 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2983,9 +2983,9 @@ DEFUN(show_ip_pim_mlag_up_vrf_all, show_ip_pim_mlag_up_vrf_all_cmd, return CMD_SUCCESS; } -DEFUN (show_ip_pim_neighbor, +DEFPY (show_ip_pim_neighbor, show_ip_pim_neighbor_cmd, - "show ip pim [vrf NAME] neighbor [detail|WORD] [json]", + "show ip pim [vrf NAME] neighbor [detail|WORD]$interface [json$json]", SHOW_STR IP_STR PIM_STR @@ -2995,25 +2995,31 @@ DEFUN (show_ip_pim_neighbor, "Name of interface or neighbor\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct vrf *v; + json_object *json_parent = NULL; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - if (argv_find(argv, argc, "detail", &idx) - || argv_find(argv, argc, "WORD", &idx)) - pim_show_neighbors_single(vrf->info, vty, argv[idx]->arg, uj); + if (json) + json_parent = json_object_new_object(); + + if (interface) + pim_show_neighbors_single(v->info, vty, interface, json_parent); else - pim_show_neighbors(vrf->info, vty, uj); + pim_show_neighbors(v->info, vty, json_parent); + + if (json) + vty_json(vty, json_parent); return CMD_SUCCESS; } -DEFUN (show_ip_pim_neighbor_vrf_all, +DEFPY (show_ip_pim_neighbor_vrf_all, show_ip_pim_neighbor_vrf_all_cmd, - "show ip pim vrf all neighbor [detail|WORD] [json]", + "show ip pim vrf all neighbor [detail|WORD]$interface [json$json]", SHOW_STR IP_STR PIM_STR @@ -3023,30 +3029,29 @@ DEFUN (show_ip_pim_neighbor_vrf_all, "Name of interface or neighbor\n" JSON_STR) { - int idx = 2; - bool uj = use_json(argc, argv); - struct vrf *vrf; - bool first = true; + struct vrf *v; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; - if (uj) - vty_out(vty, "{ "); - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (uj) { - if (!first) - vty_out(vty, ", "); - vty_out(vty, " \"%s\": ", vrf->name); - first = false; - } else - vty_out(vty, "VRF: %s\n", vrf->name); - if (argv_find(argv, argc, "detail", &idx) - || argv_find(argv, argc, "WORD", &idx)) - pim_show_neighbors_single(vrf->info, vty, - argv[idx]->arg, uj); + if (json) + json_parent = json_object_new_object(); + RB_FOREACH (v, vrf_name_head, &vrfs_by_name) { + if (!json) + vty_out(vty, "VRF: %s\n", v->name); else - pim_show_neighbors(vrf->info, vty, uj); + json_vrf = json_object_new_object(); + + if (interface) + pim_show_neighbors_single(v->info, vty, interface, + json_vrf); + else + pim_show_neighbors(v->info, vty, json_vrf); + + if (json) + json_object_object_add(json_parent, v->name, json_vrf); } - if (uj) - vty_out(vty, "}\n"); + if (json) + vty_json(vty, json_parent); return CMD_SUCCESS; } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 441a00816..0d575a145 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -2677,7 +2677,8 @@ void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty, vty_out(vty, "%% No such interface or neighbor\n"); } -void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, bool uj) +void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, + json_object *json) { struct listnode *neighnode; struct interface *ifp; @@ -2686,16 +2687,13 @@ void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, bool uj) time_t now; char uptime[10]; char expire[10]; - char neigh_src_str[INET_ADDRSTRLEN]; - json_object *json = NULL; + char neigh_src_str[PIM_ADDRSTRLEN]; json_object *json_ifp_rows = NULL; json_object *json_row = NULL; now = pim_time_monotonic_sec(); - if (uj) { - json = json_object_new_object(); - } else { + if (!json) { vty_out(vty, "Interface Neighbor Uptime Holdtime DR Pri\n"); } @@ -2709,19 +2707,19 @@ void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, bool uj) if (pim_ifp->pim_sock_fd < 0) continue; - if (uj) + if (json) 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)); + snprintfrr(neigh_src_str, sizeof(neigh_src_str), + "%pPAs", &neigh->source_addr); pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - if (uj) { + if (json) { json_row = json_object_new_object(); json_object_string_add(json_row, "interface", ifp->name); @@ -2745,12 +2743,9 @@ void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, bool uj) } } - if (uj) { + if (json) { 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 13fd40b99..00a9a5673 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -90,8 +90,9 @@ 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); + const char *neighbor, json_object *json); +void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, + json_object *json); /* * Special Macro to allow us to get the correct pim_instance */ From 9d6d0270119a54384820defa13a74200ace388aa Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Wed, 2 Mar 2022 02:33:49 -0800 Subject: [PATCH 8/8] pim6d: Adding show ipv6 pim nexthop and nexthop-lookup commands Adding new show commands to display pim nexthops and pim nexthop lookups received from zebra. Signed-off-by: Sai Gomathi N --- pimd/pim6_cmd.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++- pimd/pim_cmd.c | 64 +++++++++++++----------------------------- 2 files changed, 93 insertions(+), 45 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index aa264c475..6e12b7fd3 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -33,12 +33,14 @@ #include "pimd.h" #include "pim6_cmd.h" +#include "pim_cmd_common.h" #include "pim_vty.h" #include "lib/northbound_cli.h" #include "pim_errors.h" #include "pim_nb.h" #include "pim_addr.h" -#include "pim_cmd_common.h" +#include "pim_nht.h" + #ifndef VTYSH_EXTRACT_PL #include "pimd/pim6_cmd_clippy.c" @@ -1379,6 +1381,74 @@ DEFPY (show_ipv6_pim_neighbor_vrf_all, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_nexthop, + show_ipv6_pim_nexthop_cmd, + "show ipv6 pim [vrf NAME] nexthop", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM cached nexthop rpf information\n") +{ + struct vrf *v; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + pim_show_nexthop(v->info, vty); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_pim_nexthop_lookup, + show_ipv6_pim_nexthop_lookup_cmd, + "show ipv6 pim [vrf NAME] nexthop-lookup X:X::X:X$source X:X::X:X$group", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM cached nexthop rpf lookup\n" + "Source/RP address\n" + "Multicast Group address\n") +{ + struct prefix nht_p; + int result = 0; + pim_addr vif_source; + struct prefix grp; + struct pim_nexthop nexthop; + char nexthop_addr_str[PIM_ADDRSTRLEN]; + struct vrf *v; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + if (!pim_rp_set_upstream_addr(v->info, &vif_source, source, group)) + return CMD_SUCCESS; + + pim_addr_to_prefix(&nht_p, vif_source); + pim_addr_to_prefix(&grp, group); + memset(&nexthop, 0, sizeof(nexthop)); + + result = pim_ecmp_nexthop_lookup(v->info, &nexthop, &nht_p, &grp, 0); + + if (!result) { + vty_out(vty, + "Nexthop Lookup failed, no usable routes returned.\n"); + return CMD_SUCCESS; + } + + pim_addr_dump("", &nexthop.mrib_nexthop_addr, + nexthop_addr_str, sizeof(nexthop_addr_str)); + vty_out(vty, "Group %s --- Nexthop %s Interface %s\n", group_str, + nexthop_addr_str, nexthop.interface->name); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1452,4 +1522,6 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_local_membership_cmd); install_element(VIEW_NODE, &show_ipv6_pim_neighbor_cmd); install_element(VIEW_NODE, &show_ipv6_pim_neighbor_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_nexthop_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_nexthop_lookup_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 3b6a62d65..3f2e24848 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3488,7 +3488,7 @@ DEFPY (show_ip_pim_rpf_vrf_all, return CMD_SUCCESS; } -DEFUN (show_ip_pim_nexthop, +DEFPY (show_ip_pim_nexthop, show_ip_pim_nexthop_cmd, "show ip pim [vrf NAME] nexthop", SHOW_STR @@ -3497,20 +3497,21 @@ DEFUN (show_ip_pim_nexthop, VRF_CMD_HELP_STR "PIM cached nexthop rpf information\n") { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *v; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - pim_show_nexthop(vrf->info, vty); + pim_show_nexthop(v->info, vty); return CMD_SUCCESS; } -DEFUN (show_ip_pim_nexthop_lookup, +DEFPY (show_ip_pim_nexthop_lookup, show_ip_pim_nexthop_lookup_cmd, - "show ip pim [vrf NAME] nexthop-lookup A.B.C.D A.B.C.D", + "show ip pim [vrf NAME] nexthop-lookup A.B.C.D$source A.B.C.D$group", SHOW_STR IP_STR PIM_STR @@ -3521,61 +3522,37 @@ DEFUN (show_ip_pim_nexthop_lookup, { struct prefix nht_p; int result = 0; - struct in_addr src_addr, grp_addr; - struct in_addr vif_source; - const char *addr_str, *addr_str1; + pim_addr vif_source; struct prefix grp; struct pim_nexthop nexthop; char nexthop_addr_str[PREFIX_STRLEN]; - char grp_str[PREFIX_STRLEN]; - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *v; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - argv_find(argv, argc, "A.B.C.D", &idx); - addr_str = argv[idx]->arg; - result = inet_pton(AF_INET, addr_str, &src_addr); - if (result <= 0) { - vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, - errno, safe_strerror(errno)); - return CMD_WARNING; - } - - if (pim_is_group_224_4(src_addr)) { + if (pim_is_group_224_4(source)) { vty_out(vty, "Invalid argument. Expected Valid Source Address.\n"); return CMD_WARNING; } - addr_str1 = argv[idx + 1]->arg; - result = inet_pton(AF_INET, addr_str1, &grp_addr); - if (result <= 0) { - vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, - errno, safe_strerror(errno)); - return CMD_WARNING; - } - - if (!pim_is_group_224_4(grp_addr)) { + if (!pim_is_group_224_4(group)) { vty_out(vty, "Invalid argument. Expected Valid Multicast Group Address.\n"); return CMD_WARNING; } - if (!pim_rp_set_upstream_addr(vrf->info, &vif_source, src_addr, - grp_addr)) + if (!pim_rp_set_upstream_addr(v->info, &vif_source, source, group)) return CMD_SUCCESS; - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = vif_source; - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = grp_addr; + pim_addr_to_prefix(&nht_p, vif_source); + pim_addr_to_prefix(&grp, group); memset(&nexthop, 0, sizeof(nexthop)); - result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop, &nht_p, &grp, 0); + result = pim_ecmp_nexthop_lookup(v->info, &nexthop, &nht_p, &grp, 0); if (!result) { vty_out(vty, @@ -3583,10 +3560,9 @@ DEFUN (show_ip_pim_nexthop_lookup, return CMD_SUCCESS; } - pim_addr_dump("", &grp, grp_str, sizeof(grp_str)); pim_addr_dump("", &nexthop.mrib_nexthop_addr, nexthop_addr_str, sizeof(nexthop_addr_str)); - vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", grp_str, + vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", group_str, nexthop_addr_str, nexthop.interface->name); return CMD_SUCCESS;