From 0095f482ca70ea74c7099405accfc742ef82bdb3 Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Mon, 7 Feb 2022 02:13:16 -0800 Subject: [PATCH 1/9] pim6d: Implementing "show ipv6 pim rp-info" CLI Adding new show CLI to display pim RP information. Also corrected ipv4 json object. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 73 ++++++++++++++++++++++++--------------- pimd/pim_rp.c | 13 +++---- pimd/pim_rp.h | 3 +- 4 files changed, 144 insertions(+), 37 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 7b3e04fdc0..251d62058b 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -622,6 +622,96 @@ DEFPY (interface_no_ipv6_mld_query_interval, "frr-routing:ipv6"); } +DEFPY (show_ipv6_pim_rp, + show_ipv6_pim_rp_cmd, + "show ipv6 pim [vrf NAME] rp-info [X:X::X:X/M$group] [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM RP information\n" + "Multicast Group range\n" + JSON_STR) +{ + struct pim_instance *pim; + struct vrf *v; + json_object *json_parent = NULL; + struct prefix *range = NULL; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + 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 (group_str) { + range = prefix_new(); + prefix_copy(range, group); + apply_mask(range); + } + + if (json) + json_parent = json_object_new_object(); + + pim_rp_show_information(pim, range, vty, json_parent); + + if (json) + vty_json(vty, json_parent); + + prefix_free(&range); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_pim_rp_vrf_all, + show_ipv6_pim_rp_vrf_all_cmd, + "show ipv6 pim vrf all rp-info [X:X::X:X/M$group] [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM RP information\n" + "Multicast Group range\n" + JSON_STR) +{ + struct vrf *vrf; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; + struct prefix *range = NULL; + + if (group_str) { + range = prefix_new(); + prefix_copy(range, group); + apply_mask(range); + } + + 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_rp_show_information(vrf->info, range, vty, json_vrf); + if (json) + json_object_object_add(json_parent, vrf->name, + json_vrf); + } + if (json) + vty_json(vty, json_parent); + + prefix_free(&range); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -674,4 +764,6 @@ void pim_cmd_init(void) install_element(INTERFACE_NODE, &interface_ipv6_mld_query_interval_cmd); install_element(INTERFACE_NODE, &interface_no_ipv6_mld_query_interval_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_rp_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_rp_vrf_all_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 86d179fe39..c34135eaf6 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5402,9 +5402,9 @@ DEFUN (show_ip_pim_upstream_rpf, return CMD_SUCCESS; } -DEFUN (show_ip_pim_rp, +DEFPY (show_ip_pim_rp, show_ip_pim_rp_cmd, - "show ip pim [vrf NAME] rp-info [A.B.C.D/M] [json]", + "show ip pim [vrf NAME] rp-info [A.B.C.D/M$group] [json$json]", SHOW_STR IP_STR PIM_STR @@ -5413,28 +5413,45 @@ DEFUN (show_ip_pim_rp, "Multicast Group range\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct pim_instance *pim; + struct vrf *v; + json_object *json_parent = NULL; struct prefix *range = NULL; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - if (argv_find(argv, argc, "A.B.C.D/M", &idx)) { + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + if (group_str) { range = prefix_new(); - (void)str2prefix(argv[idx]->arg, range); + prefix_copy(range, group); apply_mask(range); } - pim_rp_show_information(vrf->info, range, vty, uj); + if (json) + json_parent = json_object_new_object(); + + pim_rp_show_information(pim, range, vty, json_parent); + + if (json) + vty_json(vty, json_parent); + + prefix_free(&range); return CMD_SUCCESS; } -DEFUN (show_ip_pim_rp_vrf_all, +DEFPY (show_ip_pim_rp_vrf_all, show_ip_pim_rp_vrf_all_cmd, - "show ip pim vrf all rp-info [A.B.C.D/M] [json]", + "show ip pim vrf all rp-info [A.B.C.D/M$group] [json$json]", SHOW_STR IP_STR PIM_STR @@ -5443,32 +5460,34 @@ DEFUN (show_ip_pim_rp_vrf_all, "Multicast Group range\n" JSON_STR) { - int idx = 0; - bool uj = use_json(argc, argv); struct vrf *vrf; - bool first = true; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; struct prefix *range = NULL; - if (argv_find(argv, argc, "A.B.C.D/M", &idx)) { + if (group_str) { range = prefix_new(); - (void)str2prefix(argv[idx]->arg, range); + prefix_copy(range, group); apply_mask(range); } - if (uj) - vty_out(vty, "{ "); + if (json) + json_parent = json_object_new_object(); + 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_rp_show_information(vrf->info, range, vty, uj); + else + json_vrf = json_object_new_object(); + pim_rp_show_information(vrf->info, range, vty, json_vrf); + if (json) + json_object_object_add(json_parent, vrf->name, + json_vrf); } - if (uj) - vty_out(vty, "}\n"); + if (json) + vty_json(vty, json_parent); + + prefix_free(&range); return CMD_SUCCESS; } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index a552e77823..730870fb33 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -1147,20 +1147,17 @@ int pim_rp_config_write(struct pim_instance *pim, struct vty *vty, } void pim_rp_show_information(struct pim_instance *pim, struct prefix *range, - struct vty *vty, bool uj) + struct vty *vty, json_object *json) { struct rp_info *rp_info; struct rp_info *prev_rp_info = NULL; struct listnode *node; char source[7]; - json_object *json = NULL; json_object *json_rp_rows = NULL; json_object *json_row = NULL; - if (uj) - json = json_object_new_object(); - else + if (!json) vty_out(vty, "RP address group/prefix-list OIF I am RP Source Group-Type\n"); for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) { @@ -1184,7 +1181,7 @@ void pim_rp_show_information(struct pim_instance *pim, struct prefix *range, strlcpy(source, "BSR", sizeof(source)); else strlcpy(source, "None", sizeof(source)); - if (uj) { + if (json) { /* * If we have moved on to a new RP then add the * entry for the previous RP @@ -1257,12 +1254,10 @@ void pim_rp_show_information(struct pim_instance *pim, struct prefix *range, prev_rp_info = rp_info; } - if (uj) { + if (json) { if (prev_rp_info && json_rp_rows) json_object_object_addf(json, json_rp_rows, "%pFXh", &prev_rp_info->rp.rpf_addr); - - vty_json(vty, json); } } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 04faeb5f26..e1bc71a3dc 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -25,6 +25,7 @@ #include "vty.h" #include "plist.h" #include "pim_rpf.h" +#include "lib/json.h" struct pim_interface; @@ -79,7 +80,7 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, pim_addr group); #define RP(P, G) pim_rp_g ((P), (G)) void pim_rp_show_information(struct pim_instance *pim, struct prefix *range, - struct vty *vty, bool uj); + struct vty *vty, json_object *json); void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr); int pim_rp_list_cmp(void *v1, void *v2); struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, From 45e26aa0b297c410cba4c4c8f98f57fa73bdff78 Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Tue, 8 Feb 2022 09:15:06 -0800 Subject: [PATCH 2/9] pimd: Moving the common functions from pim_cmd.c Moving the functions that are used by both IPV4 and IPV6 to a common file pim_cmd_common.c file Signed-off-by: Abhishek N R --- pimd/pim_cmd.c | 867 +---------------------------------------- pimd/pim_cmd.h | 9 - pimd/pim_cmd_common.c | 880 ++++++++++++++++++++++++++++++++++++++++++ pimd/pim_cmd_common.h | 22 ++ 4 files changed, 905 insertions(+), 873 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c34135eaf6..aa1ff5c925 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2015,244 +2015,6 @@ static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty, vty_out(vty, "%% No such interface or neighbor\n"); } -static void pim_show_state(struct pim_instance *pim, struct vty *vty, - const char *src_or_group, const char *group, bool uj) -{ - struct channel_oil *c_oil; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_ifp_in = NULL; - json_object *json_ifp_out = NULL; - json_object *json_source = NULL; - time_t now; - int first_oif; - now = pim_time_monotonic_sec(); - - if (uj) { - json = json_object_new_object(); - } else { - vty_out(vty, - "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted"); - vty_out(vty, - "\nActive Source Group RPT IIF OIL\n"); - } - - frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) { - char grp_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char in_ifname[INTERFACE_NAMSIZ + 1]; - char out_ifname[INTERFACE_NAMSIZ + 1]; - int oif_vif_index; - struct interface *ifp_in; - bool isRpt; - first_oif = 1; - - if ((c_oil->up && - PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) || - c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) - isRpt = true; - else - isRpt = false; - - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, - sizeof(grp_str)); - pim_inet4_dump("", c_oil->oil.mfcc_origin, src_str, - sizeof(src_str)); - ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent); - - if (ifp_in) - strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname)); - else - strlcpy(in_ifname, "", sizeof(in_ifname)); - - if (src_or_group) { - if (strcmp(src_or_group, src_str) - && strcmp(src_or_group, grp_str)) - continue; - - if (group && strcmp(group, grp_str)) - continue; - } - - if (uj) { - - /* Find the group, create it if it doesn't exist */ - 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); - } - - /* Find the source nested under the group, create it if - * it doesn't exist */ - json_object_object_get_ex(json_group, src_str, - &json_source); - - if (!json_source) { - json_source = json_object_new_object(); - json_object_object_add(json_group, src_str, - json_source); - } - - /* Find the inbound interface nested under the source, - * create it if it doesn't exist */ - json_object_object_get_ex(json_source, in_ifname, - &json_ifp_in); - - if (!json_ifp_in) { - json_ifp_in = json_object_new_object(); - json_object_object_add(json_source, in_ifname, - json_ifp_in); - json_object_int_add(json_source, "Installed", - c_oil->installed); - json_object_int_add(json_source, "installed", - c_oil->installed); - if (isRpt) - json_object_boolean_true_add( - json_source, "isRpt"); - else - json_object_boolean_false_add( - json_source, "isRpt"); - json_object_int_add(json_source, "RefCount", - c_oil->oil_ref_count); - json_object_int_add(json_source, "refCount", - c_oil->oil_ref_count); - json_object_int_add(json_source, "OilListSize", - c_oil->oil_size); - json_object_int_add(json_source, "oilListSize", - c_oil->oil_size); - json_object_int_add( - json_source, "OilRescan", - c_oil->oil_inherited_rescan); - json_object_int_add( - json_source, "oilRescan", - c_oil->oil_inherited_rescan); - json_object_int_add(json_source, "LastUsed", - c_oil->cc.lastused); - json_object_int_add(json_source, "lastUsed", - c_oil->cc.lastused); - json_object_int_add(json_source, "PacketCount", - c_oil->cc.pktcnt); - json_object_int_add(json_source, "packetCount", - c_oil->cc.pktcnt); - json_object_int_add(json_source, "ByteCount", - c_oil->cc.bytecnt); - json_object_int_add(json_source, "byteCount", - c_oil->cc.bytecnt); - json_object_int_add(json_source, - "WrongInterface", - c_oil->cc.wrong_if); - json_object_int_add(json_source, - "wrongInterface", - c_oil->cc.wrong_if); - } - } else { - vty_out(vty, "%-6d %-15s %-15s %-3s %-16s ", - c_oil->installed, src_str, grp_str, - isRpt ? "y" : "n", in_ifname); - } - - for (oif_vif_index = 0; oif_vif_index < MAXVIFS; - ++oif_vif_index) { - struct interface *ifp_out; - char oif_uptime[10]; - int ttl; - - ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; - if (ttl < 1) - continue; - - ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index); - pim_time_uptime( - oif_uptime, sizeof(oif_uptime), - now - c_oil->oif_creation[oif_vif_index]); - - if (ifp_out) - strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname)); - else - strlcpy(out_ifname, "", sizeof(out_ifname)); - - if (uj) { - json_ifp_out = json_object_new_object(); - json_object_string_add(json_ifp_out, "source", - src_str); - json_object_string_add(json_ifp_out, "group", - grp_str); - json_object_string_add(json_ifp_out, - "inboundInterface", - in_ifname); - json_object_string_add(json_ifp_out, - "outboundInterface", - out_ifname); - json_object_int_add(json_ifp_out, "installed", - c_oil->installed); - - json_object_object_add(json_ifp_in, out_ifname, - json_ifp_out); - } else { - if (first_oif) { - first_oif = 0; - vty_out(vty, "%s(%c%c%c%c%c)", - out_ifname, - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_IGMP) - ? 'I' - : ' ', - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_PIM) - ? 'J' - : ' ', - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_VXLAN) - ? 'V' - : ' ', - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_STAR) - ? '*' - : ' ', - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_MUTE) - ? 'M' - : ' '); - } else - vty_out(vty, ", %s(%c%c%c%c%c)", - out_ifname, - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_IGMP) - ? 'I' - : ' ', - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_PIM) - ? 'J' - : ' ', - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_VXLAN) - ? 'V' - : ' ', - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_STAR) - ? '*' - : ' ', - (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_MUTE) - ? 'M' - : ' '); - } - } - - if (!uj) - vty_out(vty, "\n"); - } - - - if (uj) - vty_json(vty, json); - else - vty_out(vty, "\n"); -} - static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, bool uj) { @@ -2332,307 +2094,10 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, vty_json(vty, json); } -static void pim_show_neighbors_secondary(struct pim_instance *pim, - struct vty *vty) -{ - struct interface *ifp; - - vty_out(vty, - "Interface Address Neighbor Secondary \n"); - - FOR_ALL_INTERFACES (pim->vrf, ifp) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *neighnode; - struct pim_neighbor *neigh; - char buf[PREFIX_STRLEN]; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - ifaddr = pim_ifp->primary_address; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, - neigh)) { - char neigh_src_str[INET_ADDRSTRLEN]; - struct listnode *prefix_node; - struct prefix *p; - - if (!neigh->prefix_list) - continue; - - pim_inet4_dump("", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); - - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, - prefix_node, p)) - vty_out(vty, "%-16s %-15s %-15s %-15pFX\n", - ifp->name, - inet_ntop(AF_INET, &ifaddr, - buf, sizeof(buf)), - neigh_src_str, p); - } - } -} - -static void json_object_pim_upstream_add(json_object *json, - struct pim_upstream *up) -{ - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) - json_object_boolean_true_add(json, "drJoinDesired"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) - json_object_boolean_true_add(json, "drJoinDesiredUpdated"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) - json_object_boolean_true_add(json, "firstHopRouter"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - json_object_boolean_true_add(json, "sourceIgmp"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) - json_object_boolean_true_add(json, "sourcePim"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) - json_object_boolean_true_add(json, "sourceStream"); - - /* XXX: need to print ths flag in the plain text display as well */ - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) - json_object_boolean_true_add(json, "sourceMsdp"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) - json_object_boolean_true_add(json, "sendSGRptPrune"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR) - json_object_boolean_true_add(json, "lastHopRouter"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY) - json_object_boolean_true_add(json, "disableKATExpiry"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF) - json_object_boolean_true_add(json, "staticIncomingInterface"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL) - json_object_boolean_true_add(json, - "allowIncomingInterfaceinOil"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA) - json_object_boolean_true_add(json, "noPimRegistrationData"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG) - json_object_boolean_true_add(json, "forcePimRegistration"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG) - json_object_boolean_true_add(json, "sourceVxlanOrigination"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM) - json_object_boolean_true_add(json, "sourceVxlanTermination"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN) - json_object_boolean_true_add(json, "mlagVxlan"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF) - json_object_boolean_true_add(json, - "mlagNonDesignatedForwarder"); -} - -static const char * -pim_upstream_state2brief_str(enum pim_upstream_state join_state, - char *state_str, size_t state_str_len) -{ - switch (join_state) { - case PIM_UPSTREAM_NOTJOINED: - strlcpy(state_str, "NotJ", state_str_len); - break; - case PIM_UPSTREAM_JOINED: - strlcpy(state_str, "J", state_str_len); - break; - default: - strlcpy(state_str, "Unk", state_str_len); - } - return state_str; -} - -static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, - char *state_str, size_t state_str_len) -{ - switch (reg_state) { - case PIM_REG_NOINFO: - strlcpy(state_str, "RegNI", state_str_len); - break; - case PIM_REG_JOIN: - strlcpy(state_str, "RegJ", state_str_len); - break; - case PIM_REG_JOIN_PENDING: - case PIM_REG_PRUNE: - strlcpy(state_str, "RegP", state_str_len); - break; - } - return state_str; -} - -static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, - pim_sgaddr *sg, bool uj) -{ - 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 - vty_out(vty, - "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); - - frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char uptime[10]; - char join_timer[10]; - char rs_timer[10]; - char ka_timer[10]; - char msdp_reg_timer[10]; - char state_str[PIM_REG_STATE_STR_LEN]; - - if (!pim_sgaddr_match(up->sg, *sg)) - continue; - - pim_time_uptime(uptime, sizeof(uptime), - now - up->state_transition); - pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), - up->t_join_timer); - - /* - * If the upstream is not dummy and it has a J/P timer for the - * neighbor display that - */ - if (!up->t_join_timer && up->rpf.source_nexthop.interface) { - struct pim_neighbor *nbr; - - nbr = pim_neighbor_find_prefix( - up->rpf.source_nexthop.interface, - &up->rpf.rpf_addr); - if (nbr) - pim_time_timer_to_hhmmss(join_timer, - sizeof(join_timer), - nbr->jp_timer); - } - - pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer), - up->t_rs_timer); - pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer), - up->t_ka_timer); - pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer), - up->t_msdp_reg_timer); - - pim_upstream_state2brief_str(up->join_state, state_str, sizeof(state_str)); - if (up->reg_state != PIM_REG_NOINFO) { - char tmp_str[PIM_REG_STATE_STR_LEN]; - char tmp[sizeof(state_str) + 1]; - - snprintf(tmp, sizeof(tmp), ",%s", - pim_reg_state2brief_str(up->reg_state, tmp_str, - sizeof(tmp_str))); - strlcat(state_str, tmp, sizeof(state_str)); - } - - 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, "inboundInterface", - up->rpf.source_nexthop.interface - ? up->rpf.source_nexthop.interface->name - : "Unknown"); - - /* - * The RPF address we use is slightly different - * based upon what we are looking up. - * If we have a S, list that unless - * we are the FHR, else we just put - * the RP as the rpfAddress - */ - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR || - pim_addr_is_any(up->sg.src)) { - char rpf[PREFIX_STRLEN]; - 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); - } else { - json_object_string_add(json_row, "rpfAddress", - src_str); - } - - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "state", state_str); - json_object_string_add( - json_row, "joinState", - pim_upstream_state2str(up->join_state)); - json_object_string_add( - json_row, "regState", - pim_reg_state2str(up->reg_state, state_str, sizeof(state_str))); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "joinTimer", - join_timer); - json_object_string_add(json_row, "resetTimer", - rs_timer); - json_object_string_add(json_row, "keepaliveTimer", - ka_timer); - json_object_string_add(json_row, "msdpRegTimer", - msdp_reg_timer); - json_object_int_add(json_row, "refCount", - up->ref_count); - json_object_int_add(json_row, "sptBit", up->sptbit); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out(vty, - "%-16s%-15pPAs %-15pPAs %-11s %-8s %-9s %-9s %-9s %6d\n", - up->rpf.source_nexthop.interface - ? up->rpf.source_nexthop.interface->name - : "Unknown", - &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_channel_helper(struct pim_instance *pim, - struct vty *vty, +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_ifchannel *ch, json_object *json, + bool uj) { struct pim_upstream *up = ch->upstream; json_object *json_group = NULL; @@ -2721,181 +2186,6 @@ static void pim_show_channel(struct pim_instance *pim, struct vty *vty, vty_json(vty, json); } -static void pim_show_join_desired_helper(struct pim_instance *pim, - struct vty *vty, - struct pim_upstream *up, - json_object *json, bool uj) -{ - 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, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - - 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, "%-15pPAs %-15pPAs %-6s\n", - &up->sg.src, &up->sg.grp, - pim_upstream_evaluate_join_desired(pim, up) ? "yes" - : "no"); - } -} - -static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, - bool uj) -{ - struct pim_upstream *up; - - json_object *json = NULL; - - if (uj) - json = json_object_new_object(); - else - vty_out(vty, - "Source Group EvalJD\n"); - - frr_each (rb_pim_upstream, &pim->upstream_head, up) { - /* scan all interfaces */ - pim_show_join_desired_helper(pim, vty, up, - json, uj); - } - - if (uj) - vty_json(vty, json); -} - -static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, - bool uj) -{ - struct pim_upstream *up; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - else - vty_out(vty, - "Source Group RpfIface RibNextHop RpfAddress \n"); - - frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char rpf_nexthop_str[PREFIX_STRLEN]; - char rpf_addr_str[PREFIX_STRLEN]; - struct pim_rpf *rpf; - const char *rpf_ifname; - - rpf = &up->rpf; - - pim_addr_dump("", - &rpf->source_nexthop.mrib_nexthop_addr, - rpf_nexthop_str, sizeof(rpf_nexthop_str)); - pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, - sizeof(rpf_addr_str)); - - rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; - - 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, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rpfInterface", - rpf_ifname); - json_object_string_add(json_row, "ribNexthop", - rpf_nexthop_str); - json_object_string_add(json_row, "rpfAddress", - rpf_addr_str); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s\n", - &up->sg.src, &up->sg.grp, rpf_ifname, - rpf_nexthop_str, rpf_addr_str); - } - } - - if (uj) - vty_json(vty, json); -} - -static void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, - time_t now, json_object *json) -{ - char refresh_uptime[10]; - - pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, - pim->rpf_cache_refresh_last); - - if (json) { - json_object_int_add(json, "rpfCacheRefreshDelayMsecs", - router->rpf_cache_refresh_delay_msec); - json_object_int_add( - json, "rpfCacheRefreshTimer", - pim_time_timer_remain_msec(pim->rpf_cache_refresher)); - json_object_int_add(json, "rpfCacheRefreshRequests", - pim->rpf_cache_refresh_requests); - json_object_int_add(json, "rpfCacheRefreshEvents", - pim->rpf_cache_refresh_events); - json_object_string_add(json, "rpfCacheRefreshLast", - refresh_uptime); - json_object_int_add(json, "nexthopLookups", - pim->nexthop_lookups); - json_object_int_add(json, "nexthopLookupsAvoided", - pim->nexthop_lookups_avoided); - } else { - vty_out(vty, - "RPF Cache Refresh Delay: %ld msecs\n" - "RPF Cache Refresh Timer: %ld msecs\n" - "RPF Cache Refresh Requests: %lld\n" - "RPF Cache Refresh Events: %lld\n" - "RPF Cache Refresh Last: %s\n" - "Nexthop Lookups: %lld\n" - "Nexthop Lookups Avoided: %lld\n", - router->rpf_cache_refresh_delay_msec, - pim_time_timer_remain_msec(pim->rpf_cache_refresher), - (long long)pim->rpf_cache_refresh_requests, - (long long)pim->rpf_cache_refresh_events, - refresh_uptime, (long long)pim->nexthop_lookups, - (long long)pim->nexthop_lookups_avoided); - } -} - static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty, time_t now) { @@ -2919,85 +2209,6 @@ static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty, uptime_mroute_del, (long long)pim->mroute_del_events); } -static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) -{ - struct pim_upstream *up; - time_t now = pim_time_monotonic_sec(); - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) { - json = json_object_new_object(); - show_rpf_refresh_stats(vty, pim, now, json); - } else { - show_rpf_refresh_stats(vty, pim, now, json); - vty_out(vty, "\n"); - vty_out(vty, - "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); - } - - frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char rpf_addr_str[PREFIX_STRLEN]; - char rib_nexthop_str[PREFIX_STRLEN]; - const char *rpf_ifname; - struct pim_rpf *rpf = &up->rpf; - - pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, - sizeof(rpf_addr_str)); - pim_addr_dump("", - &rpf->source_nexthop.mrib_nexthop_addr, - rib_nexthop_str, sizeof(rib_nexthop_str)); - - rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; - - 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_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rpfInterface", - rpf_ifname); - json_object_string_add(json_row, "rpfAddress", - rpf_addr_str); - json_object_string_add(json_row, "ribNexthop", - rib_nexthop_str); - json_object_int_add( - json_row, "routeMetric", - rpf->source_nexthop.mrib_route_metric); - json_object_int_add( - json_row, "routePreference", - rpf->source_nexthop.mrib_metric_preference); - json_object_object_add(json_group, src_str, json_row); - - } else { - vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s %6d %4d\n", - &up->sg.src, &up->sg.grp, rpf_ifname, - rpf_addr_str, rib_nexthop_str, - rpf->source_nexthop.mrib_route_metric, - rpf->source_nexthop.mrib_metric_preference); - } - } - - if (uj) - vty_json(vty, json); -} - struct pnc_cache_walk_data { struct vty *vty; struct pim_instance *pim; @@ -3325,78 +2536,6 @@ static void pim_show_group_rp_mappings_info(struct pim_instance *pim, vty_json(vty, json); } -/* pim statistics - just adding only bsm related now. - * We can continue to add all pim related stats here. - */ -static void pim_show_statistics(struct pim_instance *pim, struct vty *vty, - const char *ifname, bool uj) -{ - json_object *json = NULL; - struct interface *ifp; - - if (uj) { - json = json_object_new_object(); - json_object_int_add(json, "bsmRx", pim->bsm_rcvd); - json_object_int_add(json, "bsmTx", pim->bsm_sent); - json_object_int_add(json, "bsmDropped", pim->bsm_dropped); - } else { - vty_out(vty, "BSM Statistics :\n"); - vty_out(vty, "----------------\n"); - vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n", - pim->bsm_rcvd); - vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n", - pim->bsm_sent); - vty_out(vty, "Number of Dropped BSMs : %" PRIu64 "\n", - pim->bsm_dropped); - } - - vty_out(vty, "\n"); - - /* scan interfaces */ - FOR_ALL_INTERFACES (pim->vrf, ifp) { - struct pim_interface *pim_ifp = ifp->info; - - if (ifname && strcmp(ifname, ifp->name)) - continue; - - if (!pim_ifp) - continue; - - if (!uj) { - vty_out(vty, "Interface : %s\n", ifp->name); - vty_out(vty, "-------------------\n"); - vty_out(vty, - "Number of BSMs dropped due to config miss : %u\n", - pim_ifp->pim_ifstat_bsm_cfg_miss); - vty_out(vty, "Number of unicast BSMs dropped : %u\n", - pim_ifp->pim_ifstat_ucast_bsm_cfg_miss); - vty_out(vty, - "Number of BSMs dropped due to invalid scope zone : %u\n", - pim_ifp->pim_ifstat_bsm_invalid_sz); - } else { - - json_object *json_row = NULL; - - json_row = json_object_new_object(); - - json_object_string_add(json_row, "If Name", ifp->name); - json_object_int_add(json_row, "bsmDroppedConfig", - pim_ifp->pim_ifstat_bsm_cfg_miss); - json_object_int_add( - json_row, "bsmDroppedUnicast", - pim_ifp->pim_ifstat_ucast_bsm_cfg_miss); - json_object_int_add(json_row, - "bsmDroppedInvalidScopeZone", - pim_ifp->pim_ifstat_bsm_invalid_sz); - json_object_object_add(json, ifp->name, json_row); - } - vty_out(vty, "\n"); - } - - if (uj) - vty_json(vty, json); -} - static void clear_pim_statistics(struct pim_instance *pim) { struct interface *ifp; diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h index 89a4e6e699..8022eeea0e 100644 --- a/pimd/pim_cmd.h +++ b/pimd/pim_cmd.h @@ -73,13 +73,4 @@ void pim_cmd_init(void); -/* - * Special Macro to allow us to get the correct pim_instance; - */ -#define PIM_DECLVAR_CONTEXT(A, B) \ - struct vrf *A = VTY_GET_CONTEXT(vrf); \ - struct pim_instance *B = \ - (vrf) ? vrf->info : pim_get_pim_instance(VRF_DEFAULT); \ - vrf = (vrf) ? vrf : pim->vrf; - #endif /* PIM_CMD_H */ diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index c5d89f8065..6894556bfa 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -38,6 +38,16 @@ #include "pim_errors.h" #include "pim_nb.h" #include "pim_cmd_common.h" +#include "pim_mroute.h" +#include "pim_cmd.h" +#include "pim6_cmd.h" +#include "pim_cmd_common.h" +#include "pim_time.h" +#include "pim_zebra.h" +#include "pim_zlookup.h" +#include "pim_iface.h" +#include "lib/linklist.h" +#include "pim_neighbor.h" /** * Get current node VRF name. @@ -653,3 +663,873 @@ int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str, return nb_cli_apply_changes(vty, NULL); } + +void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up) +{ + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) + json_object_boolean_true_add(json, "drJoinDesired"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) + json_object_boolean_true_add(json, "drJoinDesiredUpdated"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) + json_object_boolean_true_add(json, "firstHopRouter"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + json_object_boolean_true_add(json, "sourceIgmp"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) + json_object_boolean_true_add(json, "sourcePim"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) + json_object_boolean_true_add(json, "sourceStream"); + + /* XXX: need to print ths flag in the plain text display as well */ + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) + json_object_boolean_true_add(json, "sourceMsdp"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) + json_object_boolean_true_add(json, "sendSGRptPrune"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR) + json_object_boolean_true_add(json, "lastHopRouter"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY) + json_object_boolean_true_add(json, "disableKATExpiry"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF) + json_object_boolean_true_add(json, "staticIncomingInterface"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL) + json_object_boolean_true_add(json, + "allowIncomingInterfaceinOil"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA) + json_object_boolean_true_add(json, "noPimRegistrationData"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG) + json_object_boolean_true_add(json, "forcePimRegistration"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG) + json_object_boolean_true_add(json, "sourceVxlanOrigination"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM) + json_object_boolean_true_add(json, "sourceVxlanTermination"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN) + json_object_boolean_true_add(json, "mlagVxlan"); + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF) + json_object_boolean_true_add(json, + "mlagNonDesignatedForwarder"); +} + +static const char * +pim_upstream_state2brief_str(enum pim_upstream_state join_state, + char *state_str, size_t state_str_len) +{ + switch (join_state) { + case PIM_UPSTREAM_NOTJOINED: + strlcpy(state_str, "NotJ", state_str_len); + break; + case PIM_UPSTREAM_JOINED: + strlcpy(state_str, "J", state_str_len); + break; + default: + strlcpy(state_str, "Unk", state_str_len); + } + return state_str; +} + +static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, + char *state_str, + size_t state_str_len) +{ + switch (reg_state) { + case PIM_REG_NOINFO: + strlcpy(state_str, "RegNI", state_str_len); + break; + case PIM_REG_JOIN: + strlcpy(state_str, "RegJ", state_str_len); + break; + case PIM_REG_JOIN_PENDING: + case PIM_REG_PRUNE: + strlcpy(state_str, "RegP", state_str_len); + break; + } + return state_str; +} + +void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, + time_t now, json_object *json) +{ + char refresh_uptime[10]; + + pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, + pim->rpf_cache_refresh_last); + + if (json) { + json_object_int_add(json, "rpfCacheRefreshDelayMsecs", + router->rpf_cache_refresh_delay_msec); + json_object_int_add( + json, "rpfCacheRefreshTimer", + pim_time_timer_remain_msec(pim->rpf_cache_refresher)); + json_object_int_add(json, "rpfCacheRefreshRequests", + pim->rpf_cache_refresh_requests); + json_object_int_add(json, "rpfCacheRefreshEvents", + pim->rpf_cache_refresh_events); + json_object_string_add(json, "rpfCacheRefreshLast", + refresh_uptime); + json_object_int_add(json, "nexthopLookups", + pim->nexthop_lookups); + json_object_int_add(json, "nexthopLookupsAvoided", + pim->nexthop_lookups_avoided); + } else { + vty_out(vty, + "RPF Cache Refresh Delay: %ld msecs\n" + "RPF Cache Refresh Timer: %ld msecs\n" + "RPF Cache Refresh Requests: %lld\n" + "RPF Cache Refresh Events: %lld\n" + "RPF Cache Refresh Last: %s\n" + "Nexthop Lookups: %lld\n" + "Nexthop Lookups Avoided: %lld\n", + router->rpf_cache_refresh_delay_msec, + pim_time_timer_remain_msec(pim->rpf_cache_refresher), + (long long)pim->rpf_cache_refresh_requests, + (long long)pim->rpf_cache_refresh_events, + refresh_uptime, (long long)pim->nexthop_lookups, + (long long)pim->nexthop_lookups_avoided); + } +} + +void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) +{ + struct pim_upstream *up; + time_t now = pim_time_monotonic_sec(); + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) { + json = json_object_new_object(); + show_rpf_refresh_stats(vty, pim, now, json); + } else { + show_rpf_refresh_stats(vty, pim, now, json); + vty_out(vty, "\n"); + vty_out(vty, + "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); + } + + frr_each (rb_pim_upstream, &pim->upstream_head, up) { + char rpf_addr_str[PREFIX_STRLEN]; + char rib_nexthop_str[PREFIX_STRLEN]; + const char *rpf_ifname; + struct pim_rpf *rpf = &up->rpf; + + pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, + sizeof(rpf_addr_str)); + pim_addr_dump("", + &rpf->source_nexthop.mrib_nexthop_addr, + rib_nexthop_str, sizeof(rib_nexthop_str)); + + rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; + + 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_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rpfInterface", + rpf_ifname); + json_object_string_add(json_row, "rpfAddress", + rpf_addr_str); + json_object_string_add(json_row, "ribNexthop", + rib_nexthop_str); + json_object_int_add( + json_row, "routeMetric", + rpf->source_nexthop.mrib_route_metric); + json_object_int_add( + json_row, "routePreference", + rpf->source_nexthop.mrib_metric_preference); + json_object_object_add(json_group, src_str, json_row); + + } else { + vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s %6d %4d\n", + &up->sg.src, &up->sg.grp, rpf_ifname, + rpf_addr_str, rib_nexthop_str, + rpf->source_nexthop.mrib_route_metric, + rpf->source_nexthop.mrib_metric_preference); + } + } + + if (uj) + vty_json(vty, json); +} + +void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty) +{ + struct interface *ifp; + + vty_out(vty, + "Interface Address Neighbor Secondary \n"); + + FOR_ALL_INTERFACES (pim->vrf, ifp) { + struct pim_interface *pim_ifp; + struct in_addr ifaddr; + struct listnode *neighnode; + struct pim_neighbor *neigh; + char buf[PREFIX_STRLEN]; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + ifaddr = pim_ifp->primary_address; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + char neigh_src_str[INET_ADDRSTRLEN]; + struct listnode *prefix_node; + struct prefix *p; + + if (!neigh->prefix_list) + continue; + + pim_inet4_dump("", neigh->source_addr, + neigh_src_str, sizeof(neigh_src_str)); + + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, + prefix_node, p)) + vty_out(vty, "%-16s %-15s %-15s %-15pFX\n", + ifp->name, + inet_ntop(AF_INET, &ifaddr, buf, + sizeof(buf)), + neigh_src_str, p); + } + } +} + +void pim_show_state(struct pim_instance *pim, struct vty *vty, + const char *src_or_group, const char *group, bool uj) +{ + struct channel_oil *c_oil; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_ifp_in = NULL; + json_object *json_ifp_out = NULL; + json_object *json_source = NULL; + time_t now; + int first_oif; + + now = pim_time_monotonic_sec(); + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted"); + vty_out(vty, + "\nActive Source Group RPT IIF OIL\n"); + } + + frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) { + char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char in_ifname[INTERFACE_NAMSIZ + 1]; + char out_ifname[INTERFACE_NAMSIZ + 1]; + int oif_vif_index; + struct interface *ifp_in; + bool isRpt; + + first_oif = 1; + + if ((c_oil->up && + PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) || + c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) + isRpt = true; + else + isRpt = false; + + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, + sizeof(grp_str)); + pim_inet4_dump("", c_oil->oil.mfcc_origin, src_str, + sizeof(src_str)); + ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent); + + if (ifp_in) + strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname)); + else + strlcpy(in_ifname, "", sizeof(in_ifname)); + + if (src_or_group) { + if (strcmp(src_or_group, src_str) && + strcmp(src_or_group, grp_str)) + continue; + + if (group && strcmp(group, grp_str)) + continue; + } + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + 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); + } + + /* Find the source nested under the group, create it if + * it doesn't exist + */ + json_object_object_get_ex(json_group, src_str, + &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, + json_source); + } + + /* Find the inbound interface nested under the source, + * create it if it doesn't exist + */ + json_object_object_get_ex(json_source, in_ifname, + &json_ifp_in); + + if (!json_ifp_in) { + json_ifp_in = json_object_new_object(); + json_object_object_add(json_source, in_ifname, + json_ifp_in); + json_object_int_add(json_source, "Installed", + c_oil->installed); + json_object_int_add(json_source, "installed", + c_oil->installed); + if (isRpt) + json_object_boolean_true_add( + json_source, "isRpt"); + else + json_object_boolean_false_add( + json_source, "isRpt"); + json_object_int_add(json_source, "RefCount", + c_oil->oil_ref_count); + json_object_int_add(json_source, "refCount", + c_oil->oil_ref_count); + json_object_int_add(json_source, "OilListSize", + c_oil->oil_size); + json_object_int_add(json_source, "oilListSize", + c_oil->oil_size); + json_object_int_add( + json_source, "OilRescan", + c_oil->oil_inherited_rescan); + json_object_int_add( + json_source, "oilRescan", + c_oil->oil_inherited_rescan); + json_object_int_add(json_source, "LastUsed", + c_oil->cc.lastused); + json_object_int_add(json_source, "lastUsed", + c_oil->cc.lastused); + json_object_int_add(json_source, "PacketCount", + c_oil->cc.pktcnt); + json_object_int_add(json_source, "packetCount", + c_oil->cc.pktcnt); + json_object_int_add(json_source, "ByteCount", + c_oil->cc.bytecnt); + json_object_int_add(json_source, "byteCount", + c_oil->cc.bytecnt); + json_object_int_add(json_source, + "WrongInterface", + c_oil->cc.wrong_if); + json_object_int_add(json_source, + "wrongInterface", + c_oil->cc.wrong_if); + } + } else { + vty_out(vty, "%-6d %-15s %-15s %-3s %-16s ", + c_oil->installed, src_str, grp_str, + isRpt ? "y" : "n", in_ifname); + } + + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; + ++oif_vif_index) { + struct interface *ifp_out; + char oif_uptime[10]; + int ttl; + + ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; + if (ttl < 1) + continue; + + ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index); + pim_time_uptime( + oif_uptime, sizeof(oif_uptime), + now - c_oil->oif_creation[oif_vif_index]); + + if (ifp_out) + strlcpy(out_ifname, ifp_out->name, + sizeof(out_ifname)); + else + strlcpy(out_ifname, "", + sizeof(out_ifname)); + + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", + src_str); + json_object_string_add(json_ifp_out, "group", + grp_str); + json_object_string_add(json_ifp_out, + "inboundInterface", + in_ifname); + json_object_string_add(json_ifp_out, + "outboundInterface", + out_ifname); + json_object_int_add(json_ifp_out, "installed", + c_oil->installed); + + json_object_object_add(json_ifp_in, out_ifname, + json_ifp_out); + } else { + if (first_oif) { + first_oif = 0; + vty_out(vty, "%s(%c%c%c%c%c)", + out_ifname, + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_PROTO_IGMP) + ? 'I' + : ' ', + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_PROTO_PIM) + ? 'J' + : ' ', + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_PROTO_VXLAN) + ? 'V' + : ' ', + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_PROTO_STAR) + ? '*' + : ' ', + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_MUTE) + ? 'M' + : ' '); + } else + vty_out(vty, ", %s(%c%c%c%c%c)", + out_ifname, + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_PROTO_IGMP) + ? 'I' + : ' ', + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_PROTO_PIM) + ? 'J' + : ' ', + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_PROTO_VXLAN) + ? 'V' + : ' ', + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_PROTO_STAR) + ? '*' + : ' ', + (c_oil->oif_flags + [oif_vif_index] & + PIM_OIF_FLAG_MUTE) + ? 'M' + : ' '); + } + } + + if (!uj) + vty_out(vty, "\n"); + } + + + if (uj) + vty_json(vty, json); + else + vty_out(vty, "\n"); +} + +/* pim statistics - just adding only bsm related now. + * We can continue to add all pim related stats here. + */ +void pim_show_statistics(struct pim_instance *pim, struct vty *vty, + const char *ifname, bool uj) +{ + json_object *json = NULL; + struct interface *ifp; + + if (uj) { + json = json_object_new_object(); + json_object_int_add(json, "bsmRx", pim->bsm_rcvd); + json_object_int_add(json, "bsmTx", pim->bsm_sent); + json_object_int_add(json, "bsmDropped", pim->bsm_dropped); + } else { + vty_out(vty, "BSM Statistics :\n"); + vty_out(vty, "----------------\n"); + vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n", + pim->bsm_rcvd); + vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n", + pim->bsm_sent); + vty_out(vty, "Number of Dropped BSMs : %" PRIu64 "\n", + pim->bsm_dropped); + } + + vty_out(vty, "\n"); + + /* scan interfaces */ + FOR_ALL_INTERFACES (pim->vrf, ifp) { + struct pim_interface *pim_ifp = ifp->info; + + if (ifname && strcmp(ifname, ifp->name)) + continue; + + if (!pim_ifp) + continue; + + if (!uj) { + vty_out(vty, "Interface : %s\n", ifp->name); + vty_out(vty, "-------------------\n"); + vty_out(vty, + "Number of BSMs dropped due to config miss : %u\n", + pim_ifp->pim_ifstat_bsm_cfg_miss); + vty_out(vty, "Number of unicast BSMs dropped : %u\n", + pim_ifp->pim_ifstat_ucast_bsm_cfg_miss); + vty_out(vty, + "Number of BSMs dropped due to invalid scope zone : %u\n", + pim_ifp->pim_ifstat_bsm_invalid_sz); + } else { + + json_object *json_row = NULL; + + json_row = json_object_new_object(); + + json_object_string_add(json_row, "If Name", ifp->name); + json_object_int_add(json_row, "bsmDroppedConfig", + pim_ifp->pim_ifstat_bsm_cfg_miss); + json_object_int_add( + json_row, "bsmDroppedUnicast", + pim_ifp->pim_ifstat_ucast_bsm_cfg_miss); + json_object_int_add(json_row, + "bsmDroppedInvalidScopeZone", + pim_ifp->pim_ifstat_bsm_invalid_sz); + json_object_object_add(json, ifp->name, json_row); + } + vty_out(vty, "\n"); + } + + if (uj) + vty_json(vty, json); +} + +void pim_show_upstream(struct pim_instance *pim, struct vty *vty, + pim_sgaddr *sg, bool uj) +{ + 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 + 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]; + char ka_timer[10]; + 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) + 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), + up->t_join_timer); + + /* + * If the upstream is not dummy and it has a J/P timer for the + * neighbor display that + */ + if (!up->t_join_timer && up->rpf.source_nexthop.interface) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find( + up->rpf.source_nexthop.interface, + up->rpf.rpf_addr.u.prefix4); + if (nbr) + pim_time_timer_to_hhmmss(join_timer, + sizeof(join_timer), + nbr->jp_timer); + } + + pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer), + up->t_rs_timer); + pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer), + up->t_ka_timer); + pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer), + up->t_msdp_reg_timer); + + pim_upstream_state2brief_str(up->join_state, state_str, + sizeof(state_str)); + if (up->reg_state != PIM_REG_NOINFO) { + char tmp_str[PIM_REG_STATE_STR_LEN]; + char tmp[sizeof(state_str) + 1]; + + snprintf(tmp, sizeof(tmp), ",%s", + pim_reg_state2brief_str(up->reg_state, tmp_str, + sizeof(tmp_str))); + strlcat(state_str, tmp, sizeof(state_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, "inboundInterface", + up->rpf.source_nexthop.interface + ? up->rpf.source_nexthop.interface->name + : "Unknown"); + + /* + * The RPF address we use is slightly different + * based upon what we are looking up. + * If we have a S, list that unless + * we are the FHR, else we just put + * the RP as the rpfAddress + */ + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR || + up->sg.src.s_addr == INADDR_ANY) { + char rpf[PREFIX_STRLEN]; + 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); + } else { + json_object_string_add(json_row, "rpfAddress", + src_str); + } + + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "state", state_str); + json_object_string_add( + json_row, "joinState", + pim_upstream_state2str(up->join_state)); + json_object_string_add( + json_row, "regState", + pim_reg_state2str(up->reg_state, state_str, + sizeof(state_str))); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "joinTimer", + join_timer); + json_object_string_add(json_row, "resetTimer", + rs_timer); + json_object_string_add(json_row, "keepaliveTimer", + ka_timer); + json_object_string_add(json_row, "msdpRegTimer", + msdp_reg_timer); + json_object_int_add(json_row, "refCount", + up->ref_count); + json_object_int_add(json_row, "sptBit", up->sptbit); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, + "%-16s%-15s %-15s %-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); + } + } + + if (uj) + vty_json(vty, json); +} + +static void pim_show_join_desired_helper(struct pim_instance *pim, + struct vty *vty, + struct pim_upstream *up, + json_object *json, bool uj) +{ + 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, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + + 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, "%-15s %-15s %-6s\n", src_str, grp_str, + pim_upstream_evaluate_join_desired(pim, up) ? "yes" + : "no"); + } +} + +void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj) +{ + struct pim_upstream *up; + + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, "Source Group EvalJD\n"); + + frr_each (rb_pim_upstream, &pim->upstream_head, up) { + /* scan all interfaces */ + pim_show_join_desired_helper(pim, vty, up, json, uj); + } + + if (uj) + vty_json(vty, json); +} + +void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) +{ + struct pim_upstream *up; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Source Group RpfIface RibNextHop RpfAddress \n"); + + frr_each (rb_pim_upstream, &pim->upstream_head, up) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rpf_nexthop_str[PREFIX_STRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; + struct pim_rpf *rpf; + const char *rpf_ifname; + + rpf = &up->rpf; + + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + pim_addr_dump("", + &rpf->source_nexthop.mrib_nexthop_addr, + rpf_nexthop_str, sizeof(rpf_nexthop_str)); + pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, + sizeof(rpf_addr_str)); + + rpf_ifname = + rpf->source_nexthop.interface ? rpf->source_nexthop + .interface->name + : ""; + + 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, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rpfInterface", + rpf_ifname); + json_object_string_add(json_row, "ribNexthop", + rpf_nexthop_str); + json_object_string_add(json_row, "rpfAddress", + rpf_addr_str); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, "%-15s %-15s %-16s %-15s %-15s\n", src_str, + grp_str, rpf_ifname, rpf_nexthop_str, + rpf_addr_str); + } + } + + if (uj) + vty_json(vty, json); +} diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index b7e6b6ac80..6034df6828 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -58,5 +58,27 @@ int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface, const char *group_str, const char *source_str); int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface, const char *group_str, const char *src_str); +void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up); +void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj); +void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty); +void pim_show_state(struct pim_instance *pim, struct vty *vty, + const char *src_or_group, const char *group, bool uj); +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); +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 show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, + time_t now, json_object *json); + +/* + * Special Macro to allow us to get the correct pim_instance; + */ +#define PIM_DECLVAR_CONTEXT(A, B) \ + struct vrf *A = VTY_GET_CONTEXT(vrf); \ + struct pim_instance *B = \ + (vrf) ? vrf->info : pim_get_pim_instance(VRF_DEFAULT); \ + vrf = (vrf) ? vrf : pim->vrf #endif /* PIM_CMD_COMMON_H */ From 1aa8de4687bbffe13f4d78fa9d254862c33ae3f8 Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Thu, 3 Mar 2022 23:56:19 -0800 Subject: [PATCH 3/9] pim6d: Implementing "show ipv6 pim rpf" CLI Adding new show CLI to display pim RPF information. Also corrected ipv4 json object. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 72 +++++++++++++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 62 +++++++++++++++++++++++-------------- pimd/pim_cmd_common.c | 28 ++++++++--------- pimd/pim_cmd_common.h | 6 ++-- 4 files changed, 127 insertions(+), 41 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 251d62058b..7cbd949286 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -712,6 +712,76 @@ DEFPY (show_ipv6_pim_rp_vrf_all, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_rpf, + show_ipv6_pim_rpf_cmd, + "show ipv6 pim [vrf NAME] rpf [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM cached source rpf information\n" + JSON_STR) +{ + struct pim_instance *pim; + struct vrf *v; + json_object *json_parent = NULL; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + 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 (json) + json_parent = json_object_new_object(); + + pim_show_rpf(pim, vty, json_parent); + + if (json) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_pim_rpf_vrf_all, + show_ipv6_pim_rpf_vrf_all_cmd, + "show ipv6 pim vrf all rpf [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM cached source rpf information\n" + JSON_STR) +{ + 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_rpf(vrf->info, vty, 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); @@ -766,4 +836,6 @@ void pim_cmd_init(void) &interface_no_ipv6_mld_query_interval_cmd); install_element(VIEW_NODE, &show_ipv6_pim_rp_cmd); install_element(VIEW_NODE, &show_ipv6_pim_rp_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_rpf_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_rpf_vrf_all_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index aa1ff5c925..866be77404 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4631,9 +4631,9 @@ DEFPY (show_ip_pim_rp_vrf_all, return CMD_SUCCESS; } -DEFUN (show_ip_pim_rpf, +DEFPY (show_ip_pim_rpf, show_ip_pim_rpf_cmd, - "show ip pim [vrf NAME] rpf [json]", + "show ip pim [vrf NAME] rpf [json$json]", SHOW_STR IP_STR PIM_STR @@ -4641,21 +4641,36 @@ DEFUN (show_ip_pim_rpf, "PIM cached source rpf information\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct pim_instance *pim; + 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; - pim_show_rpf(vrf->info, vty, uj); + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + if (json) + json_parent = json_object_new_object(); + + pim_show_rpf(pim, vty, json_parent); + + if (json) + vty_json(vty, json_parent); return CMD_SUCCESS; } -DEFUN (show_ip_pim_rpf_vrf_all, +DEFPY (show_ip_pim_rpf_vrf_all, show_ip_pim_rpf_vrf_all_cmd, - "show ip pim vrf all rpf [json]", + "show ip pim vrf all rpf [json$json]", SHOW_STR IP_STR PIM_STR @@ -4663,24 +4678,25 @@ DEFUN (show_ip_pim_rpf_vrf_all, "PIM cached source rpf information\n" JSON_STR) { - 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_rpf(vrf->info, vty, uj); + else + json_vrf = json_object_new_object(); + pim_show_rpf(vrf->info, vty, json_vrf); + if (json) + json_object_object_add(json_parent, vrf->name, + json_vrf); } - if (uj) - vty_out(vty, "}\n"); + if (json) + vty_json(vty, json_parent); return CMD_SUCCESS; } @@ -4998,7 +5014,7 @@ static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, vty_out(vty, "\n"); - show_rpf_refresh_stats(vty, pim, now, NULL); + pim_show_rpf_refresh_stats(vty, pim, now, NULL); vty_out(vty, "\n"); diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 6894556bfa..b8c4ef1552 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -760,8 +760,8 @@ static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, return state_str; } -void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, - time_t now, json_object *json) +void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, + time_t now, json_object *json) { char refresh_uptime[10]; @@ -802,19 +802,16 @@ void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, } } -void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) +void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json) { struct pim_upstream *up; time_t now = pim_time_monotonic_sec(); - json_object *json = NULL; json_object *json_group = NULL; json_object *json_row = NULL; - if (uj) { - json = json_object_new_object(); - show_rpf_refresh_stats(vty, pim, now, json); - } else { - show_rpf_refresh_stats(vty, pim, now, json); + pim_show_rpf_refresh_stats(vty, pim, now, json); + + if (!json) { vty_out(vty, "\n"); vty_out(vty, "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); @@ -832,9 +829,12 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) &rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str)); - rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; + rpf_ifname = + rpf->source_nexthop.interface ? rpf->source_nexthop + .interface->name + : ""; - if (uj) { + if (json) { char grp_str[PIM_ADDRSTRLEN]; char src_str[PIM_ADDRSTRLEN]; @@ -869,16 +869,14 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s %6d %4d\n", + vty_out(vty, + "%-15pPAs %-15pPAs %-16s %-15s %-15s %6d %4d\n", &up->sg.src, &up->sg.grp, rpf_ifname, rpf_addr_str, rib_nexthop_str, rpf->source_nexthop.mrib_route_metric, rpf->source_nexthop.mrib_metric_preference); } } - - if (uj) - vty_json(vty, json); } void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty) diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 6034df6828..4d80e24329 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -59,7 +59,7 @@ int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface, int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface, const char *group_str, const char *src_str); void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up); -void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj); +void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json); void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty); void pim_show_state(struct pim_instance *pim, struct vty *vty, const char *src_or_group, const char *group, bool uj); @@ -69,8 +69,8 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg, bool uj); 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 show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, - time_t now, json_object *json); +void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, + time_t now, json_object *json); /* * Special Macro to allow us to get the correct pim_instance; From 626dab7f3fc54843b34dffe6588dcf2a3b8263f5 Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Tue, 8 Feb 2022 20:32:14 -0800 Subject: [PATCH 4/9] pim6d: Implementing "show ipv6 pim secondary" CLI Adding new show CLI to display pim secondary addresses. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 30 ++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 19 ++++++++++++++----- pimd/pim_cmd_common.c | 16 +++++----------- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 7cbd949286..92ad73da25 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -782,6 +782,35 @@ DEFPY (show_ipv6_pim_rpf_vrf_all, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_secondary, + show_ipv6_pim_secondary_cmd, + "show ipv6 pim [vrf NAME] secondary", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM neighbor addresses\n") +{ + struct pim_instance *pim; + struct vrf *v; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + 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_neighbors_secondary(pim, vty); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -838,4 +867,5 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_rp_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_rpf_cmd); install_element(VIEW_NODE, &show_ipv6_pim_rpf_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_secondary_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 866be77404..1a44646071 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4301,7 +4301,7 @@ DEFUN (show_ip_pim_neighbor_vrf_all, return CMD_SUCCESS; } -DEFUN (show_ip_pim_secondary, +DEFPY (show_ip_pim_secondary, show_ip_pim_secondary_cmd, "show ip pim [vrf NAME] secondary", SHOW_STR @@ -4310,13 +4310,22 @@ DEFUN (show_ip_pim_secondary, VRF_CMD_HELP_STR "PIM neighbor addresses\n") { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct pim_instance *pim; + struct vrf *v; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - pim_show_neighbors_secondary(vrf->info, vty); + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + pim_show_neighbors_secondary(pim, vty); return CMD_SUCCESS; } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index b8c4ef1552..4ca314d8cf 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -888,10 +888,9 @@ void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty) FOR_ALL_INTERFACES (pim->vrf, ifp) { struct pim_interface *pim_ifp; - struct in_addr ifaddr; + pim_addr ifaddr; struct listnode *neighnode; struct pim_neighbor *neigh; - char buf[PREFIX_STRLEN]; pim_ifp = ifp->info; @@ -905,23 +904,18 @@ void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty) for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - char neigh_src_str[INET_ADDRSTRLEN]; struct listnode *prefix_node; struct prefix *p; if (!neigh->prefix_list) continue; - pim_inet4_dump("", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) - vty_out(vty, "%-16s %-15s %-15s %-15pFX\n", - ifp->name, - inet_ntop(AF_INET, &ifaddr, buf, - sizeof(buf)), - neigh_src_str, p); + vty_out(vty, + "%-16s %-15pPAs %-15pPAs %-15pFX\n", + ifp->name, &ifaddr, &neigh->source_addr, + p); } } } From 4f58b6aaa431128d53bf1adade64f4d34a8a7146 Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Tue, 8 Feb 2022 23:19:25 -0800 Subject: [PATCH 5/9] pim6d: Implementing "show ipv6 pim statistics" CLI Adding new show CLI to display pim statistics. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 37 +++++++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 27 ++++++++++++++++++--------- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 92ad73da25..91fdfb2650 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -811,6 +811,42 @@ DEFPY (show_ipv6_pim_secondary, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_statistics, + show_ipv6_pim_statistics_cmd, + "show ipv6 pim [vrf NAME] statistics [interface WORD$word] [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM statistics\n" + INTERFACE_STR + "PIM interface\n" + JSON_STR) +{ + struct pim_instance *pim; + struct vrf *v; + bool uj = !!json; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + 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 (word) + pim_show_statistics(pim, vty, word, uj); + else + pim_show_statistics(pim, vty, NULL, uj); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -868,4 +904,5 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_rpf_cmd); 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); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 1a44646071..bbee3c943d 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4885,9 +4885,9 @@ DEFUN (show_ip_pim_bsrp, return CMD_SUCCESS; } -DEFUN (show_ip_pim_statistics, +DEFPY (show_ip_pim_statistics, show_ip_pim_statistics_cmd, - "show ip pim [vrf NAME] statistics [interface WORD] [json]", + "show ip pim [vrf NAME] statistics [interface WORD$word] [json$json]", SHOW_STR IP_STR PIM_STR @@ -4897,17 +4897,26 @@ DEFUN (show_ip_pim_statistics, "PIM interface\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct pim_instance *pim; + struct vrf *v; + bool uj = !!json; - if (!vrf) + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) return CMD_WARNING; - if (argv_find(argv, argc, "WORD", &idx)) - pim_show_statistics(vrf->info, vty, argv[idx]->arg, uj); + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + if (word) + pim_show_statistics(pim, vty, word, uj); else - pim_show_statistics(vrf->info, vty, NULL, uj); + pim_show_statistics(pim, vty, NULL, uj); return CMD_SUCCESS; } From 95023bd72a101fe8f87b3f10e2564dd65025d318 Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Thu, 10 Feb 2022 21:15:31 -0800 Subject: [PATCH 6/9] 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; From e577f6e7d567888e0cf0634f7cf34ab6fa7da95a Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Mon, 14 Feb 2022 23:24:31 -0800 Subject: [PATCH 7/9] pim6d: Implementing "show ipv6 pim upstream-join-desired" CLI Adding new show CLI to display group join desired status. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 32 ++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 23 ++++++++++++++++------- pimd/pim_cmd_common.c | 14 ++++++++------ 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 3077ab18f3..631eb95e30 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -932,6 +932,37 @@ DEFPY (show_ipv6_pim_upstream_vrf_all, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_upstream_join_desired, + show_ipv6_pim_upstream_join_desired_cmd, + "show ipv6 pim [vrf NAME] upstream-join-desired [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM upstream join-desired\n" + JSON_STR) +{ + struct pim_instance *pim; + struct vrf *v; + bool uj = !!json; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + 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_join_desired(pim, vty, uj); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -992,4 +1023,5 @@ void pim_cmd_init(void) 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); + install_element(VIEW_NODE, &show_ipv6_pim_upstream_join_desired_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e8e336d78f..3f77b0cd65 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4509,9 +4509,9 @@ DEFUN (show_ip_pim_channel, return CMD_SUCCESS; } -DEFUN (show_ip_pim_upstream_join_desired, +DEFPY (show_ip_pim_upstream_join_desired, show_ip_pim_upstream_join_desired_cmd, - "show ip pim [vrf NAME] upstream-join-desired [json]", + "show ip pim [vrf NAME] upstream-join-desired [json$json]", SHOW_STR IP_STR PIM_STR @@ -4519,14 +4519,23 @@ DEFUN (show_ip_pim_upstream_join_desired, "PIM upstream join-desired\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct pim_instance *pim; + 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_join_desired(vrf->info, vty, uj); + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + pim_show_join_desired(pim, vty, uj); return CMD_SUCCESS; } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 9d0c1af06f..06f590ad92 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -1404,14 +1404,15 @@ static void pim_show_join_desired_helper(struct pim_instance *pim, json_object *json, bool uj) { 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]; + 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) { @@ -1431,7 +1432,8 @@ static void pim_show_join_desired_helper(struct pim_instance *pim, json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-15s %-15s %-6s\n", src_str, grp_str, + vty_out(vty, "%-15pPAs %-15pPAs %-6s\n", &up->sg.src, + &up->sg.grp, pim_upstream_evaluate_join_desired(pim, up) ? "yes" : "no"); } From b1a419baef33492752823f35fe8bdb0e68df151d Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Mon, 14 Feb 2022 23:42:40 -0800 Subject: [PATCH 8/9] pim6d: Implementing "show ipv6 pim upstream-rpf" CLI. Adding new show CLI to display pim RPF for upstreams. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 32 +++++++++++ pimd/pim_cmd.c | 23 +++++--- pimd/pim_cmd_common.c | 129 ++++++++++++++++++++++-------------------- 3 files changed, 115 insertions(+), 69 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 631eb95e30..dbe9296073 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -963,6 +963,37 @@ DEFPY (show_ipv6_pim_upstream_join_desired, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_upstream_rpf, + show_ipv6_pim_upstream_rpf_cmd, + "show ipv6 pim [vrf NAME] upstream-rpf [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM upstream source rpf\n" + JSON_STR) +{ + struct pim_instance *pim; + struct vrf *v; + bool uj = !!json; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + 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_upstream_rpf(pim, vty, uj); + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1024,4 +1055,5 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_upstream_cmd); install_element(VIEW_NODE, &show_ipv6_pim_upstream_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_upstream_join_desired_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_upstream_rpf_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 3f77b0cd65..cc113a4520 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4540,9 +4540,9 @@ DEFPY (show_ip_pim_upstream_join_desired, return CMD_SUCCESS; } -DEFUN (show_ip_pim_upstream_rpf, +DEFPY (show_ip_pim_upstream_rpf, show_ip_pim_upstream_rpf_cmd, - "show ip pim [vrf NAME] upstream-rpf [json]", + "show ip pim [vrf NAME] upstream-rpf [json$json]", SHOW_STR IP_STR PIM_STR @@ -4550,14 +4550,23 @@ DEFUN (show_ip_pim_upstream_rpf, "PIM upstream source rpf\n" JSON_STR) { - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct pim_instance *pim; + 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_upstream_rpf(vrf->info, vty, uj); + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + pim_show_upstream_rpf(pim, vty, uj); return CMD_SUCCESS; } diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 06f590ad92..ad2f474789 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -674,62 +674,64 @@ bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match) void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up) { - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) - json_object_boolean_true_add(json, "drJoinDesired"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) - json_object_boolean_true_add(json, "drJoinDesiredUpdated"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) - json_object_boolean_true_add(json, "firstHopRouter"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - json_object_boolean_true_add(json, "sourceIgmp"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) - json_object_boolean_true_add(json, "sourcePim"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) - json_object_boolean_true_add(json, "sourceStream"); - + json_object_boolean_add( + json, "drJoinDesired", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)); + json_object_boolean_add( + json, "drJoinDesiredUpdated", + CHECK_FLAG(up->flags, + PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)); + json_object_boolean_add( + json, "firstHopRouter", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FHR)); + json_object_boolean_add( + json, "sourceIgmp", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)); + json_object_boolean_add( + json, "sourcePim", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_PIM)); + json_object_boolean_add( + json, "sourceStream", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)); /* XXX: need to print ths flag in the plain text display as well */ - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) - json_object_boolean_true_add(json, "sourceMsdp"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) - json_object_boolean_true_add(json, "sendSGRptPrune"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR) - json_object_boolean_true_add(json, "lastHopRouter"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY) - json_object_boolean_true_add(json, "disableKATExpiry"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF) - json_object_boolean_true_add(json, "staticIncomingInterface"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL) - json_object_boolean_true_add(json, - "allowIncomingInterfaceinOil"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA) - json_object_boolean_true_add(json, "noPimRegistrationData"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG) - json_object_boolean_true_add(json, "forcePimRegistration"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG) - json_object_boolean_true_add(json, "sourceVxlanOrigination"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM) - json_object_boolean_true_add(json, "sourceVxlanTermination"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN) - json_object_boolean_true_add(json, "mlagVxlan"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF) - json_object_boolean_true_add(json, - "mlagNonDesignatedForwarder"); + json_object_boolean_add( + json, "sourceMsdp", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)); + json_object_boolean_add( + json, "sendSGRptPrune", + CHECK_FLAG(up->flags, + PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)); + json_object_boolean_add( + json, "lastHopRouter", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_LHR)); + json_object_boolean_add( + json, "disableKATExpiry", + CHECK_FLAG(up->flags, + PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)); + json_object_boolean_add( + json, "staticIncomingInterface", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)); + json_object_boolean_add( + json, "allowIncomingInterfaceinOil", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)); + json_object_boolean_add( + json, "noPimRegistrationData", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)); + json_object_boolean_add( + json, "forcePimRegistration", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)); + json_object_boolean_add( + json, "sourceVxlanOrigination", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)); + json_object_boolean_add( + json, "sourceVxlanTermination", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)); + json_object_boolean_add( + json, "mlagVxlan", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)); + json_object_boolean_add( + json, "mlagNonDesignatedForwarder", + CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)); } static const char * @@ -1473,8 +1475,6 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) "Source Group RpfIface RibNextHop RpfAddress \n"); frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; char rpf_nexthop_str[PREFIX_STRLEN]; char rpf_addr_str[PREFIX_STRLEN]; struct pim_rpf *rpf; @@ -1482,8 +1482,6 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) rpf = &up->rpf; - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); @@ -1496,6 +1494,13 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) : ""; 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) { @@ -1516,9 +1521,9 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) rpf_addr_str); json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-15s %-15s %-16s %-15s %-15s\n", src_str, - grp_str, rpf_ifname, rpf_nexthop_str, - rpf_addr_str); + vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s\n", + &up->sg.src, &up->sg.grp, rpf_ifname, + rpf_nexthop_str, rpf_addr_str); } } From 2d85c6714419b9b66ec8c094c9ddd469192cdf3e Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Tue, 15 Feb 2022 02:19:39 -0800 Subject: [PATCH 9/9] pim6d: Implementing "show ipv6 pim state" CLI Adding new show CLI to display pim internal state related to groups. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 76 +++++++++++++++++++++++++++++++++++++++++++ pimd/pim_cmd.c | 75 +++++++++++++++++++----------------------- pimd/pim_cmd_common.c | 55 +++++++++++++------------------ pimd/pim_cmd_common.h | 3 +- 4 files changed, 135 insertions(+), 74 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index dbe9296073..a6f8a3e52a 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -994,6 +994,80 @@ DEFPY (show_ipv6_pim_upstream_rpf, return CMD_SUCCESS; } +DEFPY (show_ipv6_pim_state, + show_ipv6_pim_state_cmd, + "show ipv6 pim [vrf NAME] state [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 state information\n" + "Unicast or Multicast address\n" + "Multicast address\n" + JSON_STR) +{ + struct pim_instance *pim; + struct vrf *v; + json_object *json_parent = NULL; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + 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 (json) + json_parent = json_object_new_object(); + + pim_show_state(pim, vty, s_or_g_str, g_str, json_parent); + + if (json) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_pim_state_vrf_all, + show_ipv6_pim_state_vrf_all_cmd, + "show ipv6 pim vrf all state [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 state information\n" + "Unicast or Multicast address\n" + "Multicast address\n" + JSON_STR) +{ + 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_state(vrf->info, vty, s_or_g_str, g_str, 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); @@ -1056,4 +1130,6 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_pim_upstream_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_upstream_join_desired_cmd); 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); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index cc113a4520..633bacadc9 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4322,9 +4322,9 @@ DEFPY (show_ip_pim_secondary, return CMD_SUCCESS; } -DEFUN (show_ip_pim_state, +DEFPY (show_ip_pim_state, show_ip_pim_state_cmd, - "show ip pim [vrf NAME] state [A.B.C.D [A.B.C.D]] [json]", + "show ip pim [vrf NAME] state [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]", SHOW_STR IP_STR PIM_STR @@ -4334,32 +4334,36 @@ DEFUN (show_ip_pim_state, "Multicast address\n" JSON_STR) { - const char *src_or_group = NULL; - const char *group = NULL; - int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct pim_instance *pim; + 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 (uj) - argc--; + pim = pim_get_pim_instance(v->vrf_id); - if (argv_find(argv, argc, "A.B.C.D", &idx)) { - src_or_group = argv[idx]->arg; - if (idx + 1 < argc) - group = argv[idx + 1]->arg; + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; } - pim_show_state(vrf->info, vty, src_or_group, group, uj); + if (json) + json_parent = json_object_new_object(); + + pim_show_state(pim, vty, s_or_g_str, g_str, json_parent); + + if (json) + vty_json(vty, json_parent); return CMD_SUCCESS; } -DEFUN (show_ip_pim_state_vrf_all, +DEFPY (show_ip_pim_state_vrf_all, show_ip_pim_state_vrf_all_cmd, - "show ip pim vrf all state [A.B.C.D [A.B.C.D]] [json]", + "show ip pim vrf all state [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]", SHOW_STR IP_STR PIM_STR @@ -4369,36 +4373,25 @@ DEFUN (show_ip_pim_state_vrf_all, "Multicast address\n" JSON_STR) { - const char *src_or_group = NULL; - const char *group = NULL; - int idx = 2; - bool uj = use_json(argc, argv); struct vrf *vrf; - bool first = true; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; - if (uj) { - vty_out(vty, "{ "); - argc--; - } - - if (argv_find(argv, argc, "A.B.C.D", &idx)) { - src_or_group = argv[idx]->arg; - if (idx + 1 < argc) - group = argv[idx + 1]->arg; - } + if (json) + json_parent = json_object_new_object(); 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_state(vrf->info, vty, src_or_group, group, uj); + else + json_vrf = json_object_new_object(); + pim_show_state(vrf->info, vty, s_or_g_str, g_str, json_vrf); + if (json) + json_object_object_add(json_parent, vrf->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 ad2f474789..11b253d1ea 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -931,10 +931,10 @@ void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty) } void pim_show_state(struct pim_instance *pim, struct vty *vty, - const char *src_or_group, const char *group, bool uj) + const char *src_or_group, const char *group, + json_object *json) { struct channel_oil *c_oil; - json_object *json = NULL; json_object *json_group = NULL; json_object *json_ifp_in = NULL; json_object *json_ifp_out = NULL; @@ -944,9 +944,7 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, now = pim_time_monotonic_sec(); - if (uj) { - json = json_object_new_object(); - } else { + if (!json) { vty_out(vty, "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted"); vty_out(vty, @@ -954,8 +952,8 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, } frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) { - char grp_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; + char src_str[PIM_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; char in_ifname[INTERFACE_NAMSIZ + 1]; char out_ifname[INTERFACE_NAMSIZ + 1]; int oif_vif_index; @@ -966,16 +964,16 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, if ((c_oil->up && PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) || - c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) + pim_addr_is_any(*oil_origin(c_oil))) isRpt = true; else isRpt = false; - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, - sizeof(grp_str)); - pim_inet4_dump("", c_oil->oil.mfcc_origin, src_str, - sizeof(src_str)); - ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent); + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + oil_mcastgrp(c_oil)); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + oil_origin(c_oil)); + ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil)); if (ifp_in) strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname)); @@ -991,7 +989,7 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, continue; } - if (uj) { + if (json) { /* Find the group, create it if it doesn't exist */ json_object_object_get_ex(json, grp_str, &json_group); @@ -1028,12 +1026,8 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, c_oil->installed); json_object_int_add(json_source, "installed", c_oil->installed); - if (isRpt) - json_object_boolean_true_add( - json_source, "isRpt"); - else - json_object_boolean_false_add( - json_source, "isRpt"); + json_object_boolean_add(json_source, "isRpt", + isRpt); json_object_int_add(json_source, "RefCount", c_oil->oil_ref_count); json_object_int_add(json_source, "refCount", @@ -1067,11 +1061,11 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, "wrongInterface", c_oil->cc.wrong_if); } - } else { - vty_out(vty, "%-6d %-15s %-15s %-3s %-16s ", - c_oil->installed, src_str, grp_str, - isRpt ? "y" : "n", in_ifname); - } + } else + vty_out(vty, "%-6d %-15pPAs %-15pPAs %-3s %-16s ", + c_oil->installed, oil_origin(c_oil), + oil_mcastgrp(c_oil), isRpt ? "y" : "n", + in_ifname); for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { @@ -1079,7 +1073,7 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, char oif_uptime[10]; int ttl; - ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; + ttl = oil_if_has(c_oil, oif_vif_index); if (ttl < 1) continue; @@ -1095,7 +1089,7 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, strlcpy(out_ifname, "", sizeof(out_ifname)); - if (uj) { + if (json) { json_ifp_out = json_object_new_object(); json_object_string_add(json_ifp_out, "source", src_str); @@ -1173,14 +1167,11 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, } } - if (!uj) + if (!json) vty_out(vty, "\n"); } - - if (uj) - vty_json(vty, json); - else + if (!json) vty_out(vty, "\n"); } diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index f1427174a2..0e8955354d 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -62,7 +62,8 @@ void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up); void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json); void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty); void pim_show_state(struct pim_instance *pim, struct vty *vty, - const char *src_or_group, const char *group, bool uj); + const char *src_or_group, const char *group, + json_object *json); 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,