Merge pull request #10676 from AbhishekNR/pim_showcli_com

This commit is contained in:
David Lamparter 2022-03-30 17:15:54 +02:00 committed by GitHub
commit c0d6ed6bc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1567 additions and 1024 deletions

View File

@ -622,6 +622,452 @@ 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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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);
@ -674,4 +1120,16 @@ 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);
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);
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);
install_element(VIEW_NODE, &show_ipv6_pim_state_cmd);
install_element(VIEW_NODE, &show_ipv6_pim_state_vrf_all_cmd);
}

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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,861 @@ 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)
{
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 */
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 *
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 pim_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, json_object *json)
{
struct pim_upstream *up;
time_t now = pim_time_monotonic_sec();
json_object *json_group = NULL;
json_object *json_row = NULL;
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");
}
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->rpf_addr, rpf_addr_str,
sizeof(rpf_addr_str));
pim_addr_dump("<nexthop?>",
&rpf->source_nexthop.mrib_nexthop_addr,
rib_nexthop_str, sizeof(rib_nexthop_str));
rpf_ifname =
rpf->source_nexthop.interface ? rpf->source_nexthop
.interface->name
: "<ifname?>";
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) {
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);
}
}
}
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;
pim_addr ifaddr;
struct listnode *neighnode;
struct pim_neighbor *neigh;
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)) {
struct listnode *prefix_node;
struct prefix *p;
if (!neigh->prefix_list)
continue;
for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
prefix_node, p))
vty_out(vty,
"%-16s %-15pPAs %-15pPAs %-15pFX\n",
ifp->name, &ifaddr, &neigh->source_addr,
p);
}
}
}
void pim_show_state(struct pim_instance *pim, struct vty *vty,
const char *src_or_group, const char *group,
json_object *json)
{
struct channel_oil *c_oil;
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 (!json) {
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 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;
struct interface *ifp_in;
bool isRpt;
first_oif = 1;
if ((c_oil->up &&
PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
pim_addr_is_any(*oil_origin(c_oil)))
isRpt = true;
else
isRpt = false;
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));
else
strlcpy(in_ifname, "<iif?>", 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 (json) {
/* 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);
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",
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 %-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) {
struct interface *ifp_out;
char oif_uptime[10];
int ttl;
ttl = oil_if_has(c_oil, 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, "<oif?>",
sizeof(out_ifname));
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);
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 (!json)
vty_out(vty, "\n");
}
if (!json)
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, json_object *json)
{
struct pim_upstream *up;
time_t now;
json_object *json_group = NULL;
json_object *json_row = NULL;
now = pim_time_monotonic_sec();
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 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 (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) {
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)) {
struct pim_rpf *rpg;
rpg = RP(pim, up->sg.grp);
json_object_string_addf(json_row, "rpfAddress",
"%pFX", &rpg->rpf_addr);
} 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);
}
}
}
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");
}
}
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 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("<nexthop?>",
&rpf->source_nexthop.mrib_nexthop_addr,
rpf_nexthop_str, sizeof(rpf_nexthop_str));
pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
sizeof(rpf_addr_str));
rpf_ifname =
rpf->source_nexthop.interface ? rpf->source_nexthop
.interface->name
: "<ifname?>";
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);
}

View File

@ -58,5 +58,29 @@ 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, 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,
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,
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;
*/
#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 */

View File

@ -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);
}
}

View File

@ -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,