From 50ba39bf4c3a454320b8ef383ac59fdfb610e385 Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Thu, 7 Apr 2022 23:52:28 -0700 Subject: [PATCH] pim6d: Implementing "show ipv6 mroute" CLI Adding new show CLI to display ipv6 mroute information. Signed-off-by: Abhishek N R --- pimd/pim6_cmd.c | 84 +++++++++++++++++++++ pimd/pim_cmd.c | 50 +++++++------ pimd/pim_cmd_common.c | 166 ++++++++++++++++++++++-------------------- pimd/pim_cmd_common.h | 4 +- 4 files changed, 199 insertions(+), 105 deletions(-) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 185ec33f9c..e69e76a5cb 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -1686,6 +1686,88 @@ DEFPY (show_ipv6_multicast_count_vrf_all, return CMD_SUCCESS; } +DEFPY (show_ipv6_mroute, + show_ipv6_mroute_cmd, + "show ipv6 mroute [vrf NAME] [X:X::X:X$s_or_g [X:X::X:X$g]] [fill$fill] [json$json]", + SHOW_STR + IPV6_STR + MROUTE_STR + VRF_CMD_HELP_STR + "The Source or Group\n" + "The Group\n" + "Fill in Assumed data\n" + JSON_STR) +{ + pim_sgaddr sg = {0}; + 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(); + + 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; + } + + show_mroute(pim, vty, &sg, !!fill, json_parent); + + if (json) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + +DEFPY (show_ipv6_mroute_vrf_all, + show_ipv6_mroute_vrf_all_cmd, + "show ipv6 mroute vrf all [fill$fill] [json$json]", + SHOW_STR + IPV6_STR + MROUTE_STR + VRF_CMD_HELP_STR + "Fill in Assumed data\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(); + show_mroute(vrf->info, vty, &sg, !!fill, 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); @@ -1786,4 +1868,6 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_multicast_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_multicast_count_cmd); install_element(VIEW_NODE, &show_ipv6_multicast_count_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_mroute_cmd); + install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index f49b7a21fb..6f862c74f6 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3781,13 +3781,13 @@ DEFPY (show_ip_mroute, pim_sgaddr sg = {0}; struct pim_instance *pim; struct vrf *v; + 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); + if (!v) return CMD_WARNING; - } + pim = pim_get_pim_instance(v->vrf_id); if (!pim) { @@ -3795,6 +3795,9 @@ DEFPY (show_ip_mroute, return CMD_WARNING; } + if (json) + 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; @@ -3802,13 +3805,18 @@ DEFPY (show_ip_mroute, } else sg.grp = s_or_g; } - show_mroute(pim, vty, &sg, !!fill, !!json); + + show_mroute(pim, vty, &sg, !!fill, json_parent); + + if (json) + vty_json(vty, json_parent); + return CMD_SUCCESS; } -DEFUN (show_ip_mroute_vrf_all, +DEFPY (show_ip_mroute_vrf_all, show_ip_mroute_vrf_all_cmd, - "show ip mroute vrf all [fill] [json]", + "show ip mroute vrf all [fill$fill] [json$json]", SHOW_STR IP_STR MROUTE_STR @@ -3817,29 +3825,25 @@ DEFUN (show_ip_mroute_vrf_all, JSON_STR) { pim_sgaddr sg = {0}; - bool uj = use_json(argc, argv); - int idx = 4; struct vrf *vrf; - bool first = true; - bool fill = false; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; - if (argv_find(argv, argc, "fill", &idx)) - fill = true; + 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); - show_mroute(vrf->info, vty, &sg, fill, uj); + else + json_vrf = json_object_new_object(); + show_mroute(vrf->info, vty, &sg, !!fill, 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 bd7b802afa..4c570c351c 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -3008,23 +3008,22 @@ void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty) show_multicast_interfaces(pim, vty, NULL); } -#if PIM_IPV == 4 -void show_mroute(struct pim_instance *pim, struct vty *vty, - pim_sgaddr *sg, bool fill, bool uj) + +void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg, + bool fill, json_object *json) { struct listnode *node; struct channel_oil *c_oil; struct static_route *s_route; time_t now; - json_object *json = NULL; json_object *json_group = NULL; json_object *json_source = NULL; json_object *json_oil = NULL; json_object *json_ifp_out = NULL; int found_oif; int first; - char grp_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; + char src_str[PIM_ADDRSTRLEN]; char in_ifname[INTERFACE_NAMSIZ + 1]; char out_ifname[INTERFACE_NAMSIZ + 1]; int oif_vif_index; @@ -3033,9 +3032,7 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, char state_str[PIM_REG_STATE_STR_LEN]; char mroute_uptime[10]; - if (uj) { - json = json_object_new_object(); - } else { + if (!json) { vty_out(vty, "IP Multicast Routing Table\n"); vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n"); vty_out(vty, @@ -3054,20 +3051,21 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, continue; if (!pim_addr_is_any(sg->grp) && - pim_addr_cmp(sg->grp, c_oil->oil.mfcc_mcastgrp)) + pim_addr_cmp(sg->grp, *oil_mcastgrp(c_oil))) continue; if (!pim_addr_is_any(sg->src) && - pim_addr_cmp(sg->src, c_oil->oil.mfcc_origin)) + pim_addr_cmp(sg->src, *oil_origin(c_oil))) continue; - 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)); + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + oil_mcastgrp(c_oil)); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + oil_origin(c_oil)); strlcpy(state_str, "S", sizeof(state_str)); /* When a non DR receives a igmp join, it creates a (*,G) - * channel_oil without any upstream creation */ + * channel_oil without any upstream creation + */ if (c_oil->up) { if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags)) strlcat(state_str, "C", sizeof(state_str)); @@ -3081,7 +3079,7 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, if (pim_channel_oil_empty(c_oil)) strlcat(state_str, "P", sizeof(state_str)); - ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent); + 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)); @@ -3092,7 +3090,7 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, pim_time_uptime(mroute_uptime, sizeof(mroute_uptime), now - c_oil->mroute_creation); - if (uj) { + if (json) { /* Find the group, create it if it doesn't exist */ json_object_object_get_ex(json, grp_str, &json_group); @@ -3116,11 +3114,10 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, } /* Find the inbound interface nested under the source, - * create it if it doesn't exist */ - json_object_string_add(json_source, "source", - src_str); - json_object_string_add(json_source, "group", - grp_str); + * create it if it doesn't exist + */ + json_object_string_add(json_source, "source", src_str); + json_object_string_add(json_source, "group", grp_str); json_object_int_add(json_source, "installed", c_oil->installed); json_object_int_add(json_source, "refCount", @@ -3142,52 +3139,57 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, struct interface *ifp_out; int ttl; - ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; + ttl = oil_if_has(c_oil, oif_vif_index); if (ttl < 1) continue; /* do not display muted OIFs */ - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_MUTE) + if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_MUTE) continue; - if (c_oil->oil.mfcc_parent == oif_vif_index && - !pim_mroute_allow_iif_in_oil(c_oil, - oif_vif_index)) + if (*oil_parent(c_oil) == oif_vif_index && + !pim_mroute_allow_iif_in_oil(c_oil, oif_vif_index)) continue; ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index); found_oif = 1; if (ifp_out) - strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname)); + strlcpy(out_ifname, ifp_out->name, + sizeof(out_ifname)); else - strlcpy(out_ifname, "", sizeof(out_ifname)); + 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); json_object_string_add(json_ifp_out, "group", grp_str); - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_PIM) + if (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_PIM) json_object_boolean_true_add( json_ifp_out, "protocolPim"); - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_IGMP) + if (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_GM) +#if PIM_IPV == 4 json_object_boolean_true_add( json_ifp_out, "protocolIgmp"); +#else + json_object_boolean_true_add( + json_ifp_out, "protocolMld"); +#endif - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_VXLAN) + if (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_VXLAN) json_object_boolean_true_add( json_ifp_out, "protocolVxlan"); - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_STAR) + if (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_STAR) json_object_boolean_true_add( json_ifp_out, "protocolInherited"); @@ -3196,7 +3198,7 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, "inboundInterface", in_ifname); json_object_int_add(json_ifp_out, "iVifI", - c_oil->oil.mfcc_parent); + *oil_parent(c_oil)); json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); @@ -3216,31 +3218,35 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, json_ifp_out); } else { proto[0] = '\0'; - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_PIM) { + if (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_PIM) { strlcpy(proto, "PIM", sizeof(proto)); } - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_IGMP) { + if (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_GM) { +#if PIM_IPV == 4 strlcpy(proto, "IGMP", sizeof(proto)); +#else + strlcpy(proto, "MLD", sizeof(proto)); +#endif } - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_VXLAN) { + if (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_VXLAN) { strlcpy(proto, "VxLAN", sizeof(proto)); } - if (c_oil->oif_flags[oif_vif_index] - & PIM_OIF_FLAG_PROTO_STAR) { + if (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_STAR) { strlcpy(proto, "STAR", sizeof(proto)); } vty_out(vty, - "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n", - src_str, grp_str, state_str, proto, - in_ifname, out_ifname, ttl, - mroute_uptime); + "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n", + oil_origin(c_oil), oil_mcastgrp(c_oil), + state_str, proto, in_ifname, out_ifname, + ttl, mroute_uptime); if (first) { src_str[0] = '\0'; @@ -3253,11 +3259,12 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, } } - if (!uj && !found_oif) { + if (!json && !found_oif) { vty_out(vty, - "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n", - src_str, grp_str, state_str, "none", in_ifname, - "none", 0, "--:--:--"); + "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n", + oil_origin(c_oil), oil_mcastgrp(c_oil), + state_str, "none", in_ifname, "none", 0, + "--:--:--"); } } @@ -3268,10 +3275,8 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, if (!s_route->c_oil.installed) continue; - pim_inet4_dump("", s_route->group, grp_str, - sizeof(grp_str)); - pim_inet4_dump("", s_route->source, src_str, - sizeof(src_str)); + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &s_route->group); + snprintfrr(src_str, sizeof(src_str), "%pPAs", &s_route->source); ifp_in = pim_if_find_by_vif_index(pim, s_route->iif); found_oif = 0; @@ -3280,7 +3285,7 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, else strlcpy(in_ifname, "", sizeof(in_ifname)); - if (uj) { + if (json) { /* Find the group, create it if it doesn't exist */ json_object_object_get_ex(json, grp_str, &json_group); @@ -3292,7 +3297,8 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, } /* Find the source nested under the group, create it if - * it doesn't exist */ + * it doesn't exist + */ json_object_object_get_ex(json_group, src_str, &json_source); @@ -3321,17 +3327,18 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index); pim_time_uptime( oif_uptime, sizeof(oif_uptime), - now - - s_route->c_oil - .oif_creation[oif_vif_index]); + now - s_route->c_oil + .oif_creation[oif_vif_index]); found_oif = 1; if (ifp_out) - strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname)); + strlcpy(out_ifname, ifp_out->name, + sizeof(out_ifname)); else - strlcpy(out_ifname, "", sizeof(out_ifname)); + 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); @@ -3344,7 +3351,7 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, in_ifname); json_object_int_add( json_ifp_out, "iVifI", - s_route->c_oil.oil.mfcc_parent); + *oil_parent(&s_route->c_oil)); json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); @@ -3362,9 +3369,10 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, json_ifp_out); } else { vty_out(vty, - "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n", - src_str, grp_str, "-", proto, in_ifname, - out_ifname, ttl, oif_uptime); + "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n", + &s_route->source, &s_route->group, "-", + proto, in_ifname, out_ifname, ttl, + oif_uptime); if (first && !fill) { src_str[0] = '\0'; grp_str[0] = '\0'; @@ -3374,18 +3382,16 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, } } - if (!uj && !found_oif) { + if (!json && !found_oif) { vty_out(vty, - "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n", - src_str, grp_str, "-", proto, in_ifname, "none", - 0, "--:--:--"); + "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n", + &s_route->source, &s_route->group, "-", proto, + in_ifname, "none", 0, "--:--:--"); } } - - if (uj) - vty_json(vty, json); } +#if PIM_IPV == 4 static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil, json_object *json, struct vty *vty) diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 52d703c95c..0a5760cc30 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -108,8 +108,8 @@ void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty); void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty, json_object *json); -void show_mroute(struct pim_instance *pim, struct vty *vty, - pim_sgaddr *sg, bool fill, bool uj); +void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg, + bool fill, json_object *json); void show_mroute_count(struct pim_instance *pim, struct vty *vty, bool uj); void show_mroute_summary(struct pim_instance *pim, struct vty *vty, -- 2.39.5