From 573a01ba1921402156e1401ec961a2cc2c970591 Mon Sep 17 00:00:00 2001 From: nsaigomathi Date: Fri, 6 Aug 2021 00:47:52 -0700 Subject: [PATCH 1/2] pimd: json support for nexthop Problems Identified: show ip pim nexthop cli didn't have json extension and show ip pim vrf all upstream have improper json format Description: show ip pim nexthop command shows the nexthops that are being used. Added json support for the command. show ip pim vrf all upstream displays upstream information for all vrfs about a S,G mroute. Formatted the json structure for this command. Signed-off-by: nsaigomathi --- pimd/pim_cmd.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 817ebcc256..119909b4c5 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1443,6 +1443,118 @@ static void igmp_show_source_retransmission(struct pim_instance *pim, } /* scan interfaces */ } +struct vty_pnc_cache_walk_data { + struct vty *vty; + struct pim_instance *pim; +}; + +struct json_pnc_cache_walk_data { + json_object *json_obj; + struct pim_instance *pim; +}; + +static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg) +{ + struct pim_nexthop_cache *pnc = bucket->data; + struct vty_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 int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet, + void *arg) +{ + struct pim_nexthop_cache *pnc = backet->data; + struct json_pnc_cache_walk_data *cwd = arg; + struct pim_instance *pim = cwd->pim; + struct nexthop *nh_node = NULL; + ifindex_t first_ifindex; + struct interface *ifp = NULL; + char buf[PREFIX_STRLEN]; + json_object *json_row = NULL; + json_object *json_ifp = NULL; + json_object *json_arr = NULL; + + 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); + json_object_object_get_ex( + cwd->json_obj, + inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, + buf, sizeof(buf)), + &json_row); + if (!json_row) { + json_row = json_object_new_object(); + json_object_string_add( + json_row, "address", + inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, + buf, sizeof(buf))); + json_object_object_add( + cwd->json_obj, + inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, + buf, sizeof(buf)), + json_row); + json_arr = json_object_new_array(); + json_object_object_add(json_row, "nextHops", json_arr); + } + json_ifp = json_object_new_object(); + json_object_string_add(json_ifp, "interface", + ifp ? ifp->name : "NULL"); + json_object_string_add(json_ifp, "nexthop", + inet_ntop(AF_INET, &nh_node->gate.ipv4, + buf, sizeof(buf))); + json_object_array_add(json_arr, json_ifp); + } + return CMD_SUCCESS; +} + +static void pim_show_nexthop_json(struct pim_instance *pim, struct vty *vty, bool uj) +{ + struct vty_pnc_cache_walk_data cwd; + struct json_pnc_cache_walk_data jcwd; + + cwd.vty = vty; + cwd.pim = pim; + jcwd.pim = pim; + + if (uj) { + jcwd.json_obj = json_object_new_object(); + } else { + vty_out(vty, "Number of registered addresses: %lu\n", + pim->rpf_hash->count); + vty_out(vty, "Address Interface Nexthop\n"); + vty_out(vty, "---------------------------------------------\n"); + } + + if (uj) { + hash_walk(pim->rpf_hash, pim_print_json_pnc_cache_walkcb, + &jcwd); + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + jcwd.json_obj, JSON_C_TO_STRING_PRETTY)); + json_object_free(jcwd.json_obj); + } else { + hash_walk(pim->rpf_hash, pim_print_vty_pnc_cache_walkcb, &cwd); + } +} + static void pim_show_bsr(struct pim_instance *pim, struct vty *vty, bool uj) @@ -2782,14 +2894,24 @@ DEFPY (show_ip_pim_rpf_vrf_all, DEFPY (show_ip_pim_nexthop, show_ip_pim_nexthop_cmd, - "show ip pim [vrf NAME] nexthop", + "show ip pim [vrf NAME] nexthop [json$json]", SHOW_STR IP_STR PIM_STR VRF_CMD_HELP_STR - "PIM cached nexthop rpf information\n") + "PIM cached nexthop rpf information\n" + JSON_STR) { - return pim_show_nexthop_cmd_helper(vrf, vty); + struct vrf *v; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + pim_show_nexthop_json(v->info, vty, !!json); + + return CMD_SUCCESS; } DEFPY (show_ip_pim_nexthop_lookup, From fc19632faa63c8a93f99dd12dbde8f51823aca98 Mon Sep 17 00:00:00 2001 From: Sai Gomathi N Date: Mon, 13 Jun 2022 01:49:03 -0700 Subject: [PATCH 2/2] pimd, pim6d: Adding json support for show ipv6 nexthop Moving the reusable code of pim_show_nexthop apis to common file pim_cmd_common.c file and adding the json support for show ipv6 pim nexthop Signed-off-by: Sai Gomathi N --- pimd/pim6_cmd.c | 7 +-- pimd/pim_cmd.c | 123 +----------------------------------------- pimd/pim_cmd_common.c | 98 +++++++++++++++++++++++++++------ pimd/pim_cmd_common.h | 4 +- 4 files changed, 89 insertions(+), 143 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 4f0758cf6a..9ff2224992 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -1076,14 +1076,15 @@ DEFPY (show_ipv6_pim_neighbor_vrf_all, DEFPY (show_ipv6_pim_nexthop, show_ipv6_pim_nexthop_cmd, - "show ipv6 pim [vrf NAME] nexthop", + "show ipv6 pim [vrf NAME] nexthop [json$json]", SHOW_STR IPV6_STR PIM_STR VRF_CMD_HELP_STR - "PIM cached nexthop rpf information\n") + "PIM cached nexthop rpf information\n" + JSON_STR) { - return pim_show_nexthop_cmd_helper(vrf, vty); + return pim_show_nexthop_cmd_helper(vrf, vty, !!json); } DEFPY (show_ipv6_pim_nexthop_lookup, diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 119909b4c5..8f3777e03e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1443,118 +1443,6 @@ static void igmp_show_source_retransmission(struct pim_instance *pim, } /* scan interfaces */ } -struct vty_pnc_cache_walk_data { - struct vty *vty; - struct pim_instance *pim; -}; - -struct json_pnc_cache_walk_data { - json_object *json_obj; - struct pim_instance *pim; -}; - -static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg) -{ - struct pim_nexthop_cache *pnc = bucket->data; - struct vty_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 int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet, - void *arg) -{ - struct pim_nexthop_cache *pnc = backet->data; - struct json_pnc_cache_walk_data *cwd = arg; - struct pim_instance *pim = cwd->pim; - struct nexthop *nh_node = NULL; - ifindex_t first_ifindex; - struct interface *ifp = NULL; - char buf[PREFIX_STRLEN]; - json_object *json_row = NULL; - json_object *json_ifp = NULL; - json_object *json_arr = NULL; - - 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); - json_object_object_get_ex( - cwd->json_obj, - inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, - buf, sizeof(buf)), - &json_row); - if (!json_row) { - json_row = json_object_new_object(); - json_object_string_add( - json_row, "address", - inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, - buf, sizeof(buf))); - json_object_object_add( - cwd->json_obj, - inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, - buf, sizeof(buf)), - json_row); - json_arr = json_object_new_array(); - json_object_object_add(json_row, "nextHops", json_arr); - } - json_ifp = json_object_new_object(); - json_object_string_add(json_ifp, "interface", - ifp ? ifp->name : "NULL"); - json_object_string_add(json_ifp, "nexthop", - inet_ntop(AF_INET, &nh_node->gate.ipv4, - buf, sizeof(buf))); - json_object_array_add(json_arr, json_ifp); - } - return CMD_SUCCESS; -} - -static void pim_show_nexthop_json(struct pim_instance *pim, struct vty *vty, bool uj) -{ - struct vty_pnc_cache_walk_data cwd; - struct json_pnc_cache_walk_data jcwd; - - cwd.vty = vty; - cwd.pim = pim; - jcwd.pim = pim; - - if (uj) { - jcwd.json_obj = json_object_new_object(); - } else { - vty_out(vty, "Number of registered addresses: %lu\n", - pim->rpf_hash->count); - vty_out(vty, "Address Interface Nexthop\n"); - vty_out(vty, "---------------------------------------------\n"); - } - - if (uj) { - hash_walk(pim->rpf_hash, pim_print_json_pnc_cache_walkcb, - &jcwd); - vty_out(vty, "%s\n", - json_object_to_json_string_ext( - jcwd.json_obj, JSON_C_TO_STRING_PRETTY)); - json_object_free(jcwd.json_obj); - } else { - hash_walk(pim->rpf_hash, pim_print_vty_pnc_cache_walkcb, &cwd); - } -} - static void pim_show_bsr(struct pim_instance *pim, struct vty *vty, bool uj) @@ -2902,16 +2790,7 @@ DEFPY (show_ip_pim_nexthop, "PIM cached nexthop rpf information\n" JSON_STR) { - struct vrf *v; - - v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); - - if (!v) - return CMD_WARNING; - - pim_show_nexthop_json(v->info, vty, !!json); - - return CMD_SUCCESS; + return pim_show_nexthop_cmd_helper(vrf, vty, !!json); } DEFPY (show_ip_pim_nexthop_lookup, diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 03689bea8d..ebd7aca519 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -2635,36 +2635,90 @@ void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty, vty_out(vty, "SSM group range : %s\n", range_str); } -struct pnc_cache_walk_data { +struct vty_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 json_pnc_cache_walk_data { + json_object *json_obj; + struct pim_instance *pim; +}; + +static int pim_print_vty_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_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; + pim_addr rpf_addr = pim_addr_from_prefix(&pnc->rpf.rpf_addr); + 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, "%-15pPAs ", &rpf_addr); vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL"); +#if PIM_IPV == 4 vty_out(vty, "%pI4 ", &nh_node->gate.ipv4); +#else + vty_out(vty, "%pI6 ", &nh_node->gate.ipv6); +#endif vty_out(vty, "\n"); } return CMD_SUCCESS; } +static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet, + void *arg) +{ + struct pim_nexthop_cache *pnc = backet->data; + struct json_pnc_cache_walk_data *cwd = arg; + struct pim_instance *pim = cwd->pim; + struct nexthop *nh_node = NULL; + ifindex_t first_ifindex; + struct interface *ifp = NULL; + char addr_str[PIM_ADDRSTRLEN]; + json_object *json_row = NULL; + json_object *json_ifp = NULL; + json_object *json_arr = NULL; + + for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) { + pim_addr rpf_addr; + + first_ifindex = nh_node->ifindex; + rpf_addr = pim_addr_from_prefix(&pnc->rpf.rpf_addr); + ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id); + snprintfrr(addr_str, sizeof(addr_str), "%pPAs", &rpf_addr); + json_object_object_get_ex(cwd->json_obj, addr_str, &json_row); + if (!json_row) { + json_row = json_object_new_object(); + json_object_string_addf(json_row, "address", "%pPAs", + &rpf_addr); + json_object_object_addf(cwd->json_obj, json_row, + "%pPAs", &rpf_addr); + json_arr = json_object_new_array(); + json_object_object_add(json_row, "nexthops", json_arr); + } + json_ifp = json_object_new_object(); + json_object_string_add(json_ifp, "interface", + ifp ? ifp->name : "NULL"); +#if PIM_IPV == 4 + json_object_string_addf(json_ifp, "nexthop", "%pI4", + &nh_node->gate.ipv4); +#else + json_object_string_addf(json_ifp, "nexthop", "%pI6", + &nh_node->gate.ipv6); +#endif + json_object_array_add(json_arr, json_ifp); + } + return CMD_SUCCESS; +} + int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty, pim_addr source, pim_addr group) { @@ -2718,7 +2772,7 @@ int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty, return CMD_SUCCESS; } -int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty) +int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty, bool uj) { struct vrf *v; @@ -2727,23 +2781,35 @@ int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty) if (!v) return CMD_WARNING; - pim_show_nexthop(v->info, vty); + pim_show_nexthop(v->info, vty, uj); return CMD_SUCCESS; } -void pim_show_nexthop(struct pim_instance *pim, struct vty *vty) +void pim_show_nexthop(struct pim_instance *pim, struct vty *vty, bool uj) { - struct pnc_cache_walk_data cwd; + struct vty_pnc_cache_walk_data cwd; + struct json_pnc_cache_walk_data jcwd; 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"); + jcwd.pim = pim; - hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd); + if (uj) { + jcwd.json_obj = json_object_new_object(); + } else { + vty_out(vty, "Number of registered addresses: %lu\n", + pim->rpf_hash->count); + vty_out(vty, "Address Interface Nexthop\n"); + vty_out(vty, "---------------------------------------------\n"); + } + + if (uj) { + hash_walk(pim->rpf_hash, pim_print_json_pnc_cache_walkcb, + &jcwd); + vty_json(vty, jcwd.json_obj); + } else + hash_walk(pim->rpf_hash, pim_print_vty_pnc_cache_walkcb, &cwd); } int pim_show_neighbors_cmd_helper(const char *vrf, struct vty *vty, diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 67e092e079..2cb031993e 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -107,8 +107,8 @@ void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty, bool uj); int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty, pim_addr source, pim_addr group); -int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty); -void pim_show_nexthop(struct pim_instance *pim, struct vty *vty); +int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty, bool uj); +void pim_show_nexthop(struct pim_instance *pim, struct vty *vty, bool uj); int pim_show_neighbors_cmd_helper(const char *vrf, struct vty *vty, const char *json, const char *interface); int pim_show_neighbors_vrf_all_cmd_helper(struct vty *vty, const char *json,