mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 18:16:43 +00:00
Merge pull request #10676 from AbhishekNR/pim_showcli_com
This commit is contained in:
commit
c0d6ed6bc4
458
pimd/pim6_cmd.c
458
pimd/pim6_cmd.c
@ -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);
|
||||
}
|
||||
|
1216
pimd/pim_cmd.c
1216
pimd/pim_cmd.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user