From 95023bd72a101fe8f87b3f10e2564dd65025d318 Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Thu, 10 Feb 2022 21:15:31 -0800 Subject: [PATCH] pim6d: Implementing "show ipv6 pim upstream" CLI Adding new show CLI to display pim upstream information. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 87 +++++++++++++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 47 ++++++++++++----------- pimd/pim_cmd_common.c | 58 ++++++++++++++--------------- pimd/pim_cmd_common.h | 3 +- 4 files changed, 142 insertions(+), 53 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 91fdfb2650..3077ab18f3 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -847,6 +847,91 @@ DEFPY (show_ipv6_pim_statistics, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_upstream, + show_ipv6_pim_upstream_cmd, + "show ipv6 pim [vrf NAME] upstream [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 upstream information\n" + "The Source or Group\n" + "The Group\n" + JSON_STR) +{ + 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); + + 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 (uj) + json_parent = json_object_new_object(); + + 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; + } + + pim_show_upstream(pim, vty, &sg, json_parent); + + if (uj) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_pim_upstream_vrf_all, + show_ipv6_pim_upstream_vrf_all_cmd, + "show ipv6 pim vrf all upstream [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM upstream information\n" + JSON_STR) +{ + pim_sgaddr sg = {0}; + struct vrf *vrf; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; + + if (json) + json_parent = json_object_new_object(); + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + if (!json) + vty_out(vty, "VRF: %s\n", vrf->name); + else + json_vrf = json_object_new_object(); + pim_show_upstream(vrf->info, vty, &sg, json_vrf); + if (json) + json_object_object_add(json_parent, vrf->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); @@ -905,4 +990,6 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_rpf_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_secondary_cmd); install_element(VIEW_NODE, &show_ipv6_pim_statistics_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_upstream_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_upstream_vrf_all_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index bbee3c943d..e8e336d78f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -80,14 +80,6 @@ static struct cmd_node debug_node = { .config_write = pim_debug_config_write, }; -static inline bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match) -{ - return (pim_addr_is_any(match.grp) || - !pim_addr_cmp(match.grp, item.grp)) && - (pim_addr_is_any(match.src) || - !pim_addr_cmp(match.src, item.src)); -} - static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[], const int argc, int *idx) { @@ -4427,6 +4419,7 @@ DEFPY (show_ip_pim_upstream, 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); @@ -4441,6 +4434,9 @@ DEFPY (show_ip_pim_upstream, return CMD_WARNING; } + if (uj) + json_parent = json_object_new_object(); + if (s_or_g.s_addr != INADDR_ANY) { if (g.s_addr != INADDR_ANY) { sg.src = s_or_g; @@ -4448,14 +4444,17 @@ DEFPY (show_ip_pim_upstream, } else sg.grp = s_or_g; } - pim_show_upstream(pim, vty, &sg, uj); + pim_show_upstream(pim, vty, &sg, json_parent); + + if (uj) + vty_json(vty, json_parent); return CMD_SUCCESS; } -DEFUN (show_ip_pim_upstream_vrf_all, +DEFPY (show_ip_pim_upstream_vrf_all, show_ip_pim_upstream_vrf_all_cmd, - "show ip pim vrf all upstream [json]", + "show ip pim vrf all upstream [json$json]", SHOW_STR IP_STR PIM_STR @@ -4464,23 +4463,27 @@ DEFUN (show_ip_pim_upstream_vrf_all, JSON_STR) { pim_sgaddr sg = {0}; - bool uj = use_json(argc, argv); struct vrf *vrf; - bool first = true; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; + + if (json) + json_parent = json_object_new_object(); - 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 + if (!json) vty_out(vty, "VRF: %s\n", vrf->name); - pim_show_upstream(vrf->info, vty, &sg, uj); + else + json_vrf = json_object_new_object(); + pim_show_upstream(vrf->info, vty, &sg, json_vrf); + if (json) + json_object_object_add(json_parent, vrf->name, + json_vrf); } + 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 4ca314d8cf..9d0c1af06f 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -664,6 +664,14 @@ int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str, return nb_cli_apply_changes(vty, NULL); } +bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match) +{ + return (pim_addr_is_any(match.grp) || + !pim_addr_cmp(match.grp, item.grp)) && + (pim_addr_is_any(match.src) || + !pim_addr_cmp(match.src, item.src)); +} + void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up) { if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) @@ -1247,25 +1255,20 @@ void pim_show_statistics(struct pim_instance *pim, struct vty *vty, } void pim_show_upstream(struct pim_instance *pim, struct vty *vty, - pim_sgaddr *sg, bool uj) + pim_sgaddr *sg, json_object *json) { struct pim_upstream *up; time_t now; - json_object *json = NULL; json_object *json_group = NULL; json_object *json_row = NULL; now = pim_time_monotonic_sec(); - if (uj) - json = json_object_new_object(); - else + if (!json) vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; char uptime[10]; char join_timer[10]; char rs_timer[10]; @@ -1273,15 +1276,9 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty, char msdp_reg_timer[10]; char state_str[PIM_REG_STATE_STR_LEN]; - if (sg->grp.s_addr != INADDR_ANY && - sg->grp.s_addr != up->sg.grp.s_addr) - continue; - if (sg->src.s_addr != INADDR_ANY && - sg->src.s_addr != up->sg.src.s_addr) + if (!pim_sgaddr_match(up->sg, *sg)) continue; - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), @@ -1294,9 +1291,9 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty, if (!up->t_join_timer && up->rpf.source_nexthop.interface) { struct pim_neighbor *nbr; - nbr = pim_neighbor_find( + nbr = pim_neighbor_find_prefix( up->rpf.source_nexthop.interface, - up->rpf.rpf_addr.u.prefix4); + &up->rpf.rpf_addr); if (nbr) pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), @@ -1322,7 +1319,15 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty, strlcat(state_str, tmp, sizeof(state_str)); } - if (uj) { + if (json) { + 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) { @@ -1347,16 +1352,12 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty, * the RP as the rpfAddress */ if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR || - up->sg.src.s_addr == INADDR_ANY) { - char rpf[PREFIX_STRLEN]; + pim_addr_is_any(up->sg.src)) { struct pim_rpf *rpg; rpg = RP(pim, up->sg.grp); - pim_inet4_dump("", - rpg->rpf_addr.u.prefix4, rpf, - sizeof(rpf)); - json_object_string_add(json_row, "rpfAddress", - rpf); + json_object_string_addf(json_row, "rpfAddress", + "%pFX", &rpg->rpf_addr); } else { json_object_string_add(json_row, "rpfAddress", src_str); @@ -1387,17 +1388,14 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty, json_object_object_add(json_group, src_str, json_row); } else { vty_out(vty, - "%-16s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n", + "%-16s%-15pPAs %-15pPAs %-11s %-8s %-9s %-9s %-9s %6d\n", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : "Unknown", - src_str, grp_str, state_str, uptime, join_timer, - rs_timer, ka_timer, up->ref_count); + &up->sg.src, &up->sg.grp, state_str, uptime, + join_timer, rs_timer, ka_timer, up->ref_count); } } - - if (uj) - vty_json(vty, json); } static void pim_show_join_desired_helper(struct pim_instance *pim, diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 4d80e24329..f1427174a2 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -66,11 +66,12 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, void pim_show_statistics(struct pim_instance *pim, struct vty *vty, const char *ifname, bool uj); void pim_show_upstream(struct pim_instance *pim, struct vty *vty, - pim_sgaddr *sg, bool uj); + pim_sgaddr *sg, json_object *json); void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj); 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); /* * Special Macro to allow us to get the correct pim_instance; -- 2.39.5