2022-02-10 09:14:41 +01:00
|
|
|
/*
|
|
|
|
* PIM for IPv6 FRR
|
|
|
|
* Copyright (C) 2022 Vmware, Inc.
|
|
|
|
* Mobashshera Rasool <mrasool@vmware.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; see the file COPYING; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "lib/json.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "if.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "zclient.h"
|
|
|
|
#include "plist.h"
|
|
|
|
#include "hash.h"
|
|
|
|
#include "nexthop.h"
|
|
|
|
#include "vrf.h"
|
|
|
|
#include "ferr.h"
|
2022-03-01 03:30:14 +01:00
|
|
|
#include "lib/srcdest_table.h"
|
2022-02-08 18:14:26 +01:00
|
|
|
#include "lib/linklist.h"
|
2022-08-03 11:22:28 +02:00
|
|
|
#include "termtable.h"
|
2022-02-10 09:14:41 +01:00
|
|
|
|
|
|
|
#include "pimd.h"
|
2022-05-06 12:36:51 +02:00
|
|
|
#include "pim_instance.h"
|
2022-02-10 09:14:41 +01:00
|
|
|
#include "pim_vty.h"
|
|
|
|
#include "lib/northbound_cli.h"
|
|
|
|
#include "pim_errors.h"
|
|
|
|
#include "pim_nb.h"
|
2022-02-08 18:15:06 +01:00
|
|
|
#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"
|
2022-02-08 18:14:26 +01:00
|
|
|
#include "pim_macro.h"
|
2022-02-08 18:15:06 +01:00
|
|
|
#include "pim_neighbor.h"
|
2022-02-08 18:14:26 +01:00
|
|
|
#include "pim_nht.h"
|
|
|
|
#include "pim_sock.h"
|
|
|
|
#include "pim_ssm.h"
|
2022-04-13 17:31:45 +02:00
|
|
|
#include "pim_static.h"
|
2022-03-02 05:50:22 +01:00
|
|
|
#include "pim_addr.h"
|
2022-04-08 07:42:03 +02:00
|
|
|
#include "pim_static.h"
|
2022-06-09 13:22:42 +02:00
|
|
|
#include "pim_util.h"
|
2022-07-07 17:03:45 +02:00
|
|
|
#include "pim6_mld.h"
|
2022-02-10 09:14:41 +01:00
|
|
|
|
2022-02-25 09:59:14 +01:00
|
|
|
/**
|
|
|
|
* Get current node VRF name.
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
* In case of failure it will print error message to user.
|
|
|
|
*
|
|
|
|
* \returns name or NULL if failed to get VRF.
|
|
|
|
*/
|
|
|
|
const char *pim_cli_get_vrf_name(struct vty *vty)
|
|
|
|
{
|
|
|
|
const struct lyd_node *vrf_node;
|
|
|
|
|
|
|
|
/* Not inside any VRF context. */
|
|
|
|
if (vty->xpath_index == 0)
|
|
|
|
return VRF_DEFAULT_NAME;
|
|
|
|
|
|
|
|
vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
|
|
|
|
if (vrf_node == NULL) {
|
|
|
|
vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return yang_dnode_get_string(vrf_node, "./name");
|
|
|
|
}
|
2022-02-10 09:14:41 +01:00
|
|
|
|
2022-01-19 09:06:41 +01:00
|
|
|
int pim_process_join_prune_cmd(struct vty *vty, const char *jpi_str)
|
|
|
|
{
|
|
|
|
char xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(xpath, "/join-prune-interval", sizeof(xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, jpi_str);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_join_prune_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
char xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(xpath, "/join-prune-interval", sizeof(xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-01-19 10:35:35 +01:00
|
|
|
|
|
|
|
int pim_process_spt_switchover_infinity_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char spt_plist_xpath[XPATH_MAXLEN];
|
|
|
|
char spt_action_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
|
|
|
|
sizeof(spt_plist_xpath));
|
|
|
|
|
|
|
|
snprintf(spt_action_xpath, sizeof(spt_action_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(spt_action_xpath, "/spt-switchover/spt-action",
|
|
|
|
sizeof(spt_action_xpath));
|
|
|
|
|
|
|
|
if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
|
|
|
|
nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
|
|
|
|
NULL);
|
|
|
|
nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
|
|
|
|
"PIM_SPT_INFINITY");
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_spt_switchover_prefixlist_cmd(struct vty *vty,
|
|
|
|
const char *plist)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char spt_plist_xpath[XPATH_MAXLEN];
|
|
|
|
char spt_action_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
|
|
|
|
sizeof(spt_plist_xpath));
|
|
|
|
|
|
|
|
snprintf(spt_action_xpath, sizeof(spt_action_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(spt_action_xpath, "/spt-switchover/spt-action",
|
|
|
|
sizeof(spt_action_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
|
|
|
|
"PIM_SPT_INFINITY");
|
|
|
|
nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
|
|
|
|
plist);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_spt_switchover_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char spt_plist_xpath[XPATH_MAXLEN];
|
|
|
|
char spt_action_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
|
|
|
|
sizeof(spt_plist_xpath));
|
|
|
|
|
|
|
|
snprintf(spt_action_xpath, sizeof(spt_action_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(spt_action_xpath, "/spt-switchover/spt-action",
|
|
|
|
sizeof(spt_action_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
|
|
|
|
nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
|
|
|
|
"PIM_SPT_IMMEDIATE");
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-01-19 14:21:20 +01:00
|
|
|
|
|
|
|
int pim_process_pim_packet_cmd(struct vty *vty, const char *packet)
|
|
|
|
{
|
|
|
|
char xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(xpath, "/packets", sizeof(xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, packet);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_pim_packet_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
char xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(xpath, "/packets", sizeof(xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-01-19 14:27:24 +01:00
|
|
|
|
|
|
|
int pim_process_keepalivetimer_cmd(struct vty *vty, const char *kat)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char ka_timer_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
|
|
|
|
"frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
|
|
|
|
kat);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_keepalivetimer_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char ka_timer_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
|
|
|
|
"frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_DESTROY, NULL);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-01-19 14:36:05 +01:00
|
|
|
|
|
|
|
int pim_process_rp_kat_cmd(struct vty *vty, const char *rpkat)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char rp_ka_timer_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
|
|
|
|
sizeof(rp_ka_timer_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
|
|
|
|
rpkat);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_rp_kat_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char rp_ka_timer[6];
|
|
|
|
char rp_ka_timer_xpath[XPATH_MAXLEN];
|
|
|
|
uint v;
|
|
|
|
char rs_timer_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
snprintf(rs_timer_xpath, sizeof(rs_timer_xpath),
|
|
|
|
FRR_PIM_ROUTER_XPATH, FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(rs_timer_xpath, "/register-suppress-time",
|
|
|
|
sizeof(rs_timer_xpath));
|
|
|
|
|
|
|
|
/* RFC4601 */
|
|
|
|
v = yang_dnode_get_uint16(vty->candidate_config->dnode,
|
|
|
|
rs_timer_xpath);
|
|
|
|
v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
|
|
|
|
if (v > UINT16_MAX)
|
|
|
|
v = UINT16_MAX;
|
|
|
|
snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%u", v);
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
|
|
|
|
sizeof(rp_ka_timer_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
|
|
|
|
rp_ka_timer);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-01-19 14:50:02 +01:00
|
|
|
|
|
|
|
int pim_process_register_suppress_cmd(struct vty *vty, const char *rst)
|
|
|
|
{
|
|
|
|
char xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(xpath, "/register-suppress-time", sizeof(xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rst);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_register_suppress_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
char xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(xpath, "/register-suppress-time", sizeof(xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-03-01 03:12:22 +01:00
|
|
|
|
|
|
|
int pim_process_ip_pim_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
|
|
|
|
2022-05-04 15:05:43 +02:00
|
|
|
int pim_process_ip_pim_passive_cmd(struct vty *vty, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
|
|
|
|
"true");
|
|
|
|
else
|
|
|
|
nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
|
|
|
|
"false");
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
|
|
|
|
2022-03-01 03:12:22 +01:00
|
|
|
int pim_process_no_ip_pim_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
const struct lyd_node *mld_enable_dnode;
|
|
|
|
char mld_if_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
int printed =
|
|
|
|
snprintf(mld_if_xpath, sizeof(mld_if_xpath),
|
|
|
|
"%s/frr-gmp:gmp/address-family[address-family='%s']",
|
|
|
|
VTY_CURR_XPATH, FRR_PIM_AF_XPATH_VAL);
|
|
|
|
|
|
|
|
if (printed >= (int)(sizeof(mld_if_xpath))) {
|
|
|
|
vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
|
|
|
|
XPATH_MAXLEN);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
|
|
|
|
FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
|
|
|
|
if (!mld_enable_dnode) {
|
|
|
|
nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY, NULL);
|
|
|
|
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
|
|
|
} else {
|
|
|
|
if (!yang_dnode_get_bool(mld_enable_dnode, ".")) {
|
|
|
|
nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY,
|
|
|
|
NULL);
|
|
|
|
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
|
|
|
} else
|
|
|
|
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
|
|
|
|
"false");
|
|
|
|
}
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
2022-03-01 03:16:32 +01:00
|
|
|
|
|
|
|
int pim_process_ip_pim_drprio_cmd(struct vty *vty, const char *drpriority_str)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
|
|
|
|
drpriority_str);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_ip_pim_drprio_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_DESTROY, NULL);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
2022-03-01 03:18:42 +01:00
|
|
|
|
|
|
|
int pim_process_ip_pim_hello_cmd(struct vty *vty, const char *hello_str,
|
|
|
|
const char *hold_str)
|
|
|
|
{
|
|
|
|
const struct lyd_node *mld_enable_dnode;
|
|
|
|
|
|
|
|
mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
|
|
|
|
FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
|
|
|
|
if (!mld_enable_dnode) {
|
|
|
|
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
|
|
|
|
"true");
|
|
|
|
} else {
|
|
|
|
if (!yang_dnode_get_bool(mld_enable_dnode, "."))
|
|
|
|
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
|
|
|
|
"true");
|
|
|
|
}
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY, hello_str);
|
|
|
|
|
|
|
|
if (hold_str)
|
|
|
|
nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
|
|
|
|
hold_str);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_ip_pim_hello_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_DESTROY, NULL);
|
|
|
|
nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
2022-03-01 03:22:19 +01:00
|
|
|
|
|
|
|
int pim_process_ip_pim_activeactive_cmd(struct vty *vty, const char *no)
|
|
|
|
{
|
|
|
|
if (no)
|
|
|
|
nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
|
|
|
|
"false");
|
|
|
|
else {
|
|
|
|
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
|
|
|
|
"true");
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
|
|
|
|
"true");
|
|
|
|
}
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
2022-03-01 03:27:52 +01:00
|
|
|
|
|
|
|
int pim_process_ip_pim_boundary_oil_cmd(struct vty *vty, const char *oil)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
|
|
|
|
oil);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_ip_pim_boundary_oil_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
2022-03-01 03:30:14 +01:00
|
|
|
|
|
|
|
int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
|
|
|
|
const char *group_str, const char *source_str)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, interface);
|
|
|
|
|
|
|
|
if (!source_str) {
|
|
|
|
char buf[SRCDEST2STR_BUFFER];
|
|
|
|
|
|
|
|
inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL, buf,
|
|
|
|
group_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL, source_str,
|
|
|
|
group_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
|
|
|
|
const char *group_str, const char *source_str)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
|
|
|
|
|
|
|
if (!source_str) {
|
|
|
|
char buf[SRCDEST2STR_BUFFER];
|
|
|
|
|
|
|
|
inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL, buf,
|
|
|
|
group_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL, source_str,
|
|
|
|
group_str);
|
|
|
|
}
|
2022-03-07 07:02:10 +01:00
|
|
|
|
|
|
|
int pim_process_rp_cmd(struct vty *vty, const char *rp_str,
|
|
|
|
const char *group_str)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char rp_group_xpath[XPATH_MAXLEN];
|
|
|
|
int result = 0;
|
|
|
|
struct prefix group;
|
2022-03-07 07:46:10 +01:00
|
|
|
pim_addr rp_addr;
|
2022-03-07 07:02:10 +01:00
|
|
|
|
|
|
|
result = str2prefix(group_str, &group);
|
|
|
|
if (result) {
|
|
|
|
struct prefix temp;
|
|
|
|
|
|
|
|
prefix_copy(&temp, &group);
|
|
|
|
apply_mask(&temp);
|
|
|
|
if (!prefix_same(&group, &temp)) {
|
|
|
|
vty_out(vty, "%% Inconsistent address and mask: %s\n",
|
|
|
|
group_str);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
vty_out(vty, "%% Bad group address specified: %s\n", group_str);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
2022-03-07 07:46:10 +01:00
|
|
|
result = inet_pton(PIM_AF, rp_str, &rp_addr);
|
2022-03-07 07:02:10 +01:00
|
|
|
if (result <= 0) {
|
|
|
|
vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(rp_group_xpath, sizeof(rp_group_xpath),
|
2022-03-07 07:46:10 +01:00
|
|
|
FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL, rp_str);
|
2022-03-07 07:02:10 +01:00
|
|
|
strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_rp_cmd(struct vty *vty, const char *rp_str,
|
|
|
|
const char *group_str)
|
|
|
|
{
|
|
|
|
char group_list_xpath[XPATH_MAXLEN];
|
|
|
|
char group_xpath[XPATH_MAXLEN];
|
|
|
|
char rp_xpath[XPATH_MAXLEN];
|
|
|
|
int printed;
|
|
|
|
const char *vrfname;
|
|
|
|
const struct lyd_node *group_dnode;
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
|
2022-03-07 07:46:10 +01:00
|
|
|
"frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
|
2022-03-07 07:02:10 +01:00
|
|
|
|
|
|
|
printed = snprintf(group_list_xpath, sizeof(group_list_xpath),
|
|
|
|
"%s/group-list", rp_xpath);
|
|
|
|
|
|
|
|
if (printed >= (int)(sizeof(group_list_xpath))) {
|
|
|
|
vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
|
|
|
|
XPATH_MAXLEN);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
printed = snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
|
|
|
|
group_list_xpath, group_str);
|
|
|
|
|
|
|
|
if (printed >= (int)(sizeof(group_xpath))) {
|
|
|
|
vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
|
|
|
|
XPATH_MAXLEN);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
2022-03-11 18:57:10 +01:00
|
|
|
group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
|
|
|
|
if (!group_dnode) {
|
2022-03-07 07:02:10 +01:00
|
|
|
vty_out(vty, "%% Unable to find specified RP\n");
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (yang_is_last_list_dnode(group_dnode))
|
|
|
|
nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
|
|
|
|
else
|
|
|
|
nb_cli_enqueue_change(vty, group_list_xpath, NB_OP_DESTROY,
|
|
|
|
group_str);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-03-07 08:18:47 +01:00
|
|
|
|
|
|
|
int pim_process_rp_plist_cmd(struct vty *vty, const char *rp_str,
|
|
|
|
const char *prefix_list)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char rp_plist_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
|
|
|
|
FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL, rp_str);
|
|
|
|
strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY, prefix_list);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
|
|
|
|
const char *prefix_list)
|
|
|
|
{
|
|
|
|
char rp_xpath[XPATH_MAXLEN];
|
|
|
|
char plist_xpath[XPATH_MAXLEN];
|
|
|
|
const char *vrfname;
|
|
|
|
const struct lyd_node *plist_dnode;
|
|
|
|
const char *plist;
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
|
|
|
|
"frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
|
|
|
|
|
|
|
|
snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
|
|
|
|
"frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
|
|
|
|
strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
|
|
|
|
|
|
|
|
plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
|
|
|
|
if (!plist_dnode) {
|
|
|
|
vty_out(vty, "%% Unable to find specified RP\n");
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
plist = yang_dnode_get_string(plist_dnode, plist_xpath);
|
|
|
|
if (strcmp(prefix_list, plist)) {
|
|
|
|
vty_out(vty, "%% Unable to find specified RP\n");
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-02-08 18:15:06 +01:00
|
|
|
|
2022-02-11 06:15:31 +01:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2022-02-08 18:14:26 +01:00
|
|
|
void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
|
|
|
|
{
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
json_object_string_add(json, "name", ifp->name);
|
|
|
|
json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
|
|
|
|
json_object_string_addf(json, "address", "%pPA",
|
|
|
|
&pim_ifp->primary_address);
|
|
|
|
json_object_int_add(json, "index", ifp->ifindex);
|
|
|
|
|
|
|
|
if (if_is_multicast(ifp))
|
|
|
|
json_object_boolean_true_add(json, "flagMulticast");
|
|
|
|
|
|
|
|
if (if_is_broadcast(ifp))
|
|
|
|
json_object_boolean_true_add(json, "flagBroadcast");
|
|
|
|
|
|
|
|
if (ifp->flags & IFF_ALLMULTI)
|
|
|
|
json_object_boolean_true_add(json, "flagAllMulticast");
|
|
|
|
|
|
|
|
if (ifp->flags & IFF_PROMISC)
|
|
|
|
json_object_boolean_true_add(json, "flagPromiscuous");
|
|
|
|
|
|
|
|
if (PIM_IF_IS_DELETED(ifp))
|
|
|
|
json_object_boolean_true_add(json, "flagDeleted");
|
|
|
|
|
|
|
|
if (pim_if_lan_delay_enabled(ifp))
|
|
|
|
json_object_boolean_true_add(json, "lanDelayEnabled");
|
|
|
|
}
|
|
|
|
|
|
|
|
void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
|
|
|
|
{
|
|
|
|
vty_out(vty, "Flags\n");
|
|
|
|
vty_out(vty, "-----\n");
|
|
|
|
vty_out(vty, "All Multicast : %s\n",
|
|
|
|
(ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
|
|
|
|
vty_out(vty, "Broadcast : %s\n",
|
|
|
|
if_is_broadcast(ifp) ? "yes" : "no");
|
|
|
|
vty_out(vty, "Deleted : %s\n",
|
|
|
|
PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
|
|
|
|
vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
|
|
|
|
vty_out(vty, "Multicast : %s\n",
|
|
|
|
if_is_multicast(ifp) ? "yes" : "no");
|
|
|
|
vty_out(vty, "Promiscuous : %s\n",
|
|
|
|
(ifp->flags & IFF_PROMISC) ? "yes" : "no");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
}
|
|
|
|
|
2022-02-08 18:15:06 +01:00
|
|
|
void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
|
|
|
|
{
|
2022-02-15 08:42:40 +01:00
|
|
|
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));
|
2022-02-08 18:15:06 +01:00
|
|
|
/* XXX: need to print ths flag in the plain text display as well */
|
2022-02-15 08:42:40 +01:00
|
|
|
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));
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-03-04 08:56:19 +01:00
|
|
|
void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
|
|
|
|
time_t now, json_object *json)
|
2022-02-08 18:15:06 +01:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-04 08:56:19 +01:00
|
|
|
void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
|
2022-02-08 18:15:06 +01:00
|
|
|
{
|
|
|
|
struct pim_upstream *up;
|
|
|
|
time_t now = pim_time_monotonic_sec();
|
2022-08-11 13:10:00 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-02-08 18:15:06 +01:00
|
|
|
json_object *json_group = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
2022-03-04 08:56:19 +01:00
|
|
|
pim_show_rpf_refresh_stats(vty, pim, now, json);
|
|
|
|
|
|
|
|
if (!json) {
|
2022-02-08 18:15:06 +01:00
|
|
|
vty_out(vty, "\n");
|
2022-08-11 13:10:00 +02:00
|
|
|
|
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(
|
|
|
|
tt,
|
|
|
|
"Source|Group|RpfIface|RpfAddress|RibNextHop|Metric|Pref");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
|
|
|
|
const char *rpf_ifname;
|
|
|
|
struct pim_rpf *rpf = &up->rpf;
|
|
|
|
|
2022-03-04 08:56:19 +01:00
|
|
|
rpf_ifname =
|
|
|
|
rpf->source_nexthop.interface ? rpf->source_nexthop
|
|
|
|
.interface->name
|
|
|
|
: "<ifname?>";
|
2022-02-08 18:15:06 +01:00
|
|
|
|
2022-03-04 08:56:19 +01:00
|
|
|
if (json) {
|
2022-02-08 18:15:06 +01:00
|
|
|
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);
|
2022-04-27 10:55:57 +02:00
|
|
|
json_object_string_addf(json_row, "rpfAddress", "%pPA",
|
|
|
|
&rpf->rpf_addr);
|
2022-04-06 16:33:41 +02:00
|
|
|
json_object_string_addf(
|
|
|
|
json_row, "ribNexthop", "%pPAs",
|
|
|
|
&rpf->source_nexthop.mrib_nexthop_addr);
|
2022-02-08 18:15:06 +01:00
|
|
|
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 {
|
2022-08-11 13:10:00 +02:00
|
|
|
ttable_add_row(
|
|
|
|
tt, "%pPAs|%pPAs|%s|%pPA|%pPAs|%d|%d",
|
2022-02-08 18:15:06 +01:00
|
|
|
&up->sg.src, &up->sg.grp, rpf_ifname,
|
2022-04-27 10:55:57 +02:00
|
|
|
&rpf->rpf_addr,
|
2022-04-06 16:33:41 +02:00
|
|
|
&rpf->source_nexthop.mrib_nexthop_addr,
|
2022-02-08 18:15:06 +01:00
|
|
|
rpf->source_nexthop.mrib_route_metric,
|
|
|
|
rpf->source_nexthop.mrib_metric_preference);
|
|
|
|
}
|
|
|
|
}
|
2022-08-11 13:10:00 +02:00
|
|
|
/* Dump the generated table. */
|
|
|
|
if (!json) {
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
|
|
|
}
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
|
|
|
|
{
|
|
|
|
struct interface *ifp;
|
2022-08-11 13:22:33 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-02-08 18:15:06 +01:00
|
|
|
|
2022-08-11 13:22:33 +02:00
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(tt, "Interface|Address|Neighbor|Secondary");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
2022-02-08 18:15:06 +01:00
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
struct pim_interface *pim_ifp;
|
2022-02-09 05:32:14 +01:00
|
|
|
pim_addr ifaddr;
|
2022-02-08 18:15:06 +01:00
|
|
|
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))
|
2022-08-11 13:22:33 +02:00
|
|
|
ttable_add_row(tt, "%s|%pPAs|%pPAs|%pFX",
|
|
|
|
ifp->name, &ifaddr,
|
|
|
|
&neigh->source_addr, p);
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
}
|
2022-08-11 13:22:33 +02:00
|
|
|
/* Dump the generated table. */
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void pim_show_state(struct pim_instance *pim, struct vty *vty,
|
2022-02-15 11:19:39 +01:00
|
|
|
const char *src_or_group, const char *group,
|
|
|
|
json_object *json)
|
2022-02-08 18:15:06 +01:00
|
|
|
{
|
|
|
|
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();
|
|
|
|
|
2022-02-15 11:19:39 +01:00
|
|
|
if (!json) {
|
2022-02-08 18:15:06 +01:00
|
|
|
vty_out(vty,
|
pim6d: Fix the Code for MLD in the show pim state command
show ip pim state should show IGMP Report while
show ipv6 pim state should show MLD Report.
Output After Fix:
frr# do sh ip pim state
Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted
Active Source Group RPT IIF OIL
frr# do sh ipv6 pim state
Codes: J -> Pim Join, I -> MLD Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted
Active Source Group RPT IIF OIL
frr#
Issue: #11249
Signed-off-by: Mobashshera Rasool <mrasool@vmware.com>
2022-08-30 12:02:25 +02:00
|
|
|
"Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
|
2022-02-08 18:15:06 +01:00
|
|
|
vty_out(vty,
|
|
|
|
"\nActive Source Group RPT IIF OIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
2022-02-15 11:19:39 +01:00
|
|
|
char src_str[PIM_ADDRSTRLEN];
|
|
|
|
char grp_str[PIM_ADDRSTRLEN];
|
2022-02-08 18:15:06 +01:00
|
|
|
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)) ||
|
2022-02-15 11:19:39 +01:00
|
|
|
pim_addr_is_any(*oil_origin(c_oil)))
|
2022-02-08 18:15:06 +01:00
|
|
|
isRpt = true;
|
|
|
|
else
|
|
|
|
isRpt = false;
|
|
|
|
|
2022-02-15 11:19:39 +01:00
|
|
|
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));
|
2022-02-08 18:15:06 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-02-15 11:19:39 +01:00
|
|
|
if (json) {
|
2022-02-08 18:15:06 +01:00
|
|
|
|
|
|
|
/* 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);
|
2022-02-15 11:19:39 +01:00
|
|
|
json_object_boolean_add(json_source, "isRpt",
|
|
|
|
isRpt);
|
2022-02-08 18:15:06 +01:00
|
|
|
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);
|
|
|
|
}
|
2022-02-15 11:19:39 +01:00
|
|
|
} 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);
|
2022-02-08 18:15:06 +01:00
|
|
|
|
|
|
|
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
|
|
|
|
++oif_vif_index) {
|
|
|
|
struct interface *ifp_out;
|
|
|
|
char oif_uptime[10];
|
|
|
|
int ttl;
|
|
|
|
|
2022-02-15 11:19:39 +01:00
|
|
|
ttl = oil_if_has(c_oil, oif_vif_index);
|
2022-02-08 18:15:06 +01:00
|
|
|
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));
|
|
|
|
|
2022-02-15 11:19:39 +01:00
|
|
|
if (json) {
|
2022-02-08 18:15:06 +01:00
|
|
|
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] &
|
2022-04-13 10:00:50 +02:00
|
|
|
PIM_OIF_FLAG_PROTO_GM)
|
2022-02-08 18:15:06 +01:00
|
|
|
? '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] &
|
2022-04-13 10:00:50 +02:00
|
|
|
PIM_OIF_FLAG_PROTO_GM)
|
2022-02-08 18:15:06 +01:00
|
|
|
? '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'
|
|
|
|
: ' ');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-15 11:19:39 +01:00
|
|
|
if (!json)
|
2022-02-08 18:15:06 +01:00
|
|
|
vty_out(vty, "\n");
|
|
|
|
}
|
|
|
|
|
2022-02-15 11:19:39 +01:00
|
|
|
if (!json)
|
2022-02-08 18:15:06 +01:00
|
|
|
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,
|
2022-02-11 06:15:31 +01:00
|
|
|
pim_sgaddr *sg, json_object *json)
|
2022-02-08 18:15:06 +01:00
|
|
|
{
|
|
|
|
struct pim_upstream *up;
|
2022-08-11 13:38:02 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-02-08 18:15:06 +01:00
|
|
|
time_t now;
|
|
|
|
json_object *json_group = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
now = pim_time_monotonic_sec();
|
|
|
|
|
2022-08-11 13:38:02 +02:00
|
|
|
if (!json) {
|
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(
|
|
|
|
tt,
|
|
|
|
"Iif|Source|Group|State|Uptime|JoinTimer|RSTimer|KATimer|RefCnt");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
|
|
|
}
|
2022-02-08 18:15:06 +01:00
|
|
|
|
|
|
|
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];
|
|
|
|
|
2022-02-11 06:15:31 +01:00
|
|
|
if (!pim_sgaddr_match(up->sg, *sg))
|
2022-02-08 18:15:06 +01:00
|
|
|
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;
|
|
|
|
|
2022-04-27 10:55:57 +02:00
|
|
|
nbr = pim_neighbor_find(
|
2022-02-08 18:15:06 +01:00
|
|
|
up->rpf.source_nexthop.interface,
|
2022-04-27 10:55:57 +02:00
|
|
|
up->rpf.rpf_addr);
|
2022-02-08 18:15:06 +01:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2022-02-11 06:15:31 +01:00
|
|
|
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);
|
|
|
|
|
2022-02-08 18:15:06 +01:00
|
|
|
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 ||
|
2022-02-11 06:15:31 +01:00
|
|
|
pim_addr_is_any(up->sg.src)) {
|
2022-02-08 18:15:06 +01:00
|
|
|
struct pim_rpf *rpg;
|
|
|
|
|
|
|
|
rpg = RP(pim, up->sg.grp);
|
2022-02-11 06:15:31 +01:00
|
|
|
json_object_string_addf(json_row, "rpfAddress",
|
2022-04-27 10:55:57 +02:00
|
|
|
"%pPA", &rpg->rpf_addr);
|
2022-02-08 18:15:06 +01:00
|
|
|
} 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 {
|
2022-08-11 13:38:02 +02:00
|
|
|
ttable_add_row(tt,
|
|
|
|
"%s|%pPAs|%pPAs|%s|%s|%s|%s|%s|%d",
|
2022-02-08 18:15:06 +01:00
|
|
|
up->rpf.source_nexthop.interface
|
|
|
|
? up->rpf.source_nexthop.interface->name
|
|
|
|
: "Unknown",
|
2022-02-11 06:15:31 +01:00
|
|
|
&up->sg.src, &up->sg.grp, state_str, uptime,
|
|
|
|
join_timer, rs_timer, ka_timer, up->ref_count);
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
}
|
2022-08-11 13:38:02 +02:00
|
|
|
/* Dump the generated table. */
|
|
|
|
if (!json) {
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
|
|
|
}
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void pim_show_join_desired_helper(struct pim_instance *pim,
|
|
|
|
struct vty *vty,
|
|
|
|
struct pim_upstream *up,
|
2022-08-11 13:47:12 +02:00
|
|
|
json_object *json, bool uj,
|
|
|
|
struct ttable *tt)
|
2022-02-08 18:15:06 +01:00
|
|
|
{
|
|
|
|
json_object *json_group = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
if (uj) {
|
2022-02-15 08:24:31 +01:00
|
|
|
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);
|
|
|
|
|
2022-02-08 18:15:06 +01:00
|
|
|
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 {
|
2022-08-11 13:47:12 +02:00
|
|
|
ttable_add_row(tt, "%pPAs|%pPAs|%s", &up->sg.src, &up->sg.grp,
|
|
|
|
pim_upstream_evaluate_join_desired(pim, up)
|
|
|
|
? "yes"
|
|
|
|
: "no");
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj)
|
|
|
|
{
|
|
|
|
struct pim_upstream *up;
|
2022-08-11 13:47:12 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-02-08 18:15:06 +01:00
|
|
|
|
|
|
|
json_object *json = NULL;
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
json = json_object_new_object();
|
2022-08-11 13:47:12 +02:00
|
|
|
else {
|
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(tt, "Source|Group|EvalJD");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
|
|
|
}
|
2022-02-08 18:15:06 +01:00
|
|
|
|
|
|
|
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
|
|
|
|
/* scan all interfaces */
|
2022-08-11 13:47:12 +02:00
|
|
|
pim_show_join_desired_helper(pim, vty, up, json, uj, tt);
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
vty_json(vty, json);
|
2022-08-11 13:47:12 +02:00
|
|
|
else {
|
|
|
|
/* Dump the generated table. */
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
|
|
|
}
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
|
|
|
|
{
|
|
|
|
struct pim_upstream *up;
|
2022-08-11 13:54:21 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-02-08 18:15:06 +01:00
|
|
|
json_object *json = NULL;
|
|
|
|
json_object *json_group = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
json = json_object_new_object();
|
2022-08-11 13:54:21 +02:00
|
|
|
else {
|
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(tt,
|
|
|
|
"Source|Group|RpfIface|RibNextHop|RpfAddress");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
|
|
|
}
|
2022-02-08 18:15:06 +01:00
|
|
|
|
|
|
|
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
|
|
|
|
struct pim_rpf *rpf;
|
|
|
|
const char *rpf_ifname;
|
|
|
|
|
|
|
|
rpf = &up->rpf;
|
|
|
|
|
|
|
|
rpf_ifname =
|
|
|
|
rpf->source_nexthop.interface ? rpf->source_nexthop
|
|
|
|
.interface->name
|
|
|
|
: "<ifname?>";
|
|
|
|
|
|
|
|
if (uj) {
|
2022-02-15 08:42:40 +01:00
|
|
|
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);
|
2022-02-08 18:15:06 +01:00
|
|
|
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);
|
2022-04-06 16:33:41 +02:00
|
|
|
json_object_string_addf(
|
|
|
|
json_row, "ribNexthop", "%pPAs",
|
|
|
|
&rpf->source_nexthop.mrib_nexthop_addr);
|
2022-04-27 10:55:57 +02:00
|
|
|
json_object_string_addf(json_row, "rpfAddress", "%pPA",
|
|
|
|
&rpf->rpf_addr);
|
2022-02-08 18:15:06 +01:00
|
|
|
json_object_object_add(json_group, src_str, json_row);
|
|
|
|
} else {
|
2022-08-11 13:54:21 +02:00
|
|
|
ttable_add_row(tt, "%pPAs|%pPAs|%s|%pPA|%pPA",
|
|
|
|
&up->sg.src, &up->sg.grp, rpf_ifname,
|
|
|
|
&rpf->source_nexthop.mrib_nexthop_addr,
|
|
|
|
&rpf->rpf_addr);
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
vty_json(vty, json);
|
2022-08-11 13:54:21 +02:00
|
|
|
else {
|
|
|
|
/* Dump the generated table. */
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
|
|
|
}
|
2022-02-08 18:15:06 +01:00
|
|
|
}
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
|
|
|
|
struct pim_ifchannel *ch, json_object *json,
|
2022-03-02 05:50:22 +01:00
|
|
|
time_t now)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
|
|
|
json_object *json_iface = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
json_object *json_grp = NULL;
|
|
|
|
pim_addr ifaddr;
|
|
|
|
char uptime[10];
|
|
|
|
char expire[10];
|
|
|
|
char prune[10];
|
|
|
|
|
|
|
|
ifaddr = pim_ifp->primary_address;
|
|
|
|
|
|
|
|
pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
|
|
|
|
pim_time_timer_to_mmss(expire, sizeof(expire),
|
|
|
|
ch->t_ifjoin_expiry_timer);
|
|
|
|
pim_time_timer_to_mmss(prune, sizeof(prune),
|
|
|
|
ch->t_ifjoin_prune_pending_timer);
|
|
|
|
|
2022-03-02 05:50:22 +01:00
|
|
|
if (json) {
|
2022-02-08 18:14:26 +01:00
|
|
|
char ch_grp_str[PIM_ADDRSTRLEN];
|
|
|
|
|
|
|
|
json_object_object_get_ex(json, ch->interface->name,
|
|
|
|
&json_iface);
|
|
|
|
|
|
|
|
if (!json_iface) {
|
|
|
|
json_iface = json_object_new_object();
|
|
|
|
json_object_pim_ifp_add(json_iface, ch->interface);
|
|
|
|
json_object_object_add(json, ch->interface->name,
|
|
|
|
json_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_row = json_object_new_object();
|
2022-03-02 05:50:22 +01:00
|
|
|
json_object_string_addf(json_row, "source", "%pPAs",
|
|
|
|
&ch->sg.src);
|
|
|
|
json_object_string_addf(json_row, "group", "%pPAs",
|
|
|
|
&ch->sg.grp);
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object_string_add(json_row, "upTime", uptime);
|
|
|
|
json_object_string_add(json_row, "expire", expire);
|
|
|
|
json_object_string_add(json_row, "prune", prune);
|
|
|
|
json_object_string_add(
|
|
|
|
json_row, "channelJoinName",
|
|
|
|
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
|
|
|
|
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
|
|
|
|
#if CONFDATE > 20230131
|
|
|
|
CPP_NOTICE(
|
|
|
|
"Remove JSON object commands with keys starting with capital")
|
|
|
|
#endif
|
|
|
|
json_object_int_add(json_row, "SGRpt", 1);
|
|
|
|
json_object_int_add(json_row, "sgRpt", 1);
|
|
|
|
}
|
|
|
|
if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
|
|
|
|
json_object_int_add(json_row, "protocolPim", 1);
|
|
|
|
if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
|
|
|
|
json_object_int_add(json_row, "protocolIgmp", 1);
|
2022-03-02 05:50:22 +01:00
|
|
|
snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
|
|
|
|
&ch->sg.grp);
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
|
|
|
|
if (!json_grp) {
|
|
|
|
json_grp = json_object_new_object();
|
2022-03-02 05:50:22 +01:00
|
|
|
json_object_object_addf(json_grp, json_row, "%pPAs",
|
|
|
|
&ch->sg.src);
|
|
|
|
json_object_object_addf(json_iface, json_grp, "%pPAs",
|
|
|
|
&ch->sg.grp);
|
2022-02-08 18:14:26 +01:00
|
|
|
} else
|
2022-03-02 05:50:22 +01:00
|
|
|
json_object_object_addf(json_grp, json_row, "%pPAs",
|
|
|
|
&ch->sg.src);
|
2022-02-08 18:14:26 +01:00
|
|
|
} else {
|
2022-03-02 05:50:22 +01:00
|
|
|
vty_out(vty,
|
|
|
|
"%-16s %-15pPAs %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
|
|
|
|
ch->interface->name, &ifaddr, &ch->sg.src, &ch->sg.grp,
|
2022-02-08 18:14:26 +01:00
|
|
|
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
|
|
|
|
uptime, expire, prune);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-10 07:43:52 +02:00
|
|
|
int pim_show_join_cmd_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
|
|
|
|
pim_addr g, const char *json)
|
|
|
|
{
|
|
|
|
pim_sgaddr sg = {};
|
|
|
|
struct vrf *v;
|
|
|
|
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;
|
|
|
|
}
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-10 07:43:52 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
|
|
|
|
pim_show_join(pim, vty, &sg, json_parent);
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_join_vrf_all_cmd_helper(struct vty *vty, const char *json)
|
|
|
|
{
|
|
|
|
pim_sgaddr sg = {0};
|
|
|
|
struct vrf *vrf_struct;
|
|
|
|
json_object *json_parent = NULL;
|
|
|
|
json_object *json_vrf = NULL;
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
|
|
|
|
RB_FOREACH (vrf_struct, vrf_name_head, &vrfs_by_name) {
|
|
|
|
if (!json_parent)
|
|
|
|
vty_out(vty, "VRF: %s\n", vrf_struct->name);
|
|
|
|
else
|
|
|
|
json_vrf = json_object_new_object();
|
|
|
|
pim_show_join(vrf_struct->info, vty, &sg, json_vrf);
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_object_object_add(json_parent, vrf_struct->name,
|
|
|
|
json_vrf);
|
|
|
|
}
|
|
|
|
if (json)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
2022-03-02 05:50:22 +01:00
|
|
|
void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
|
|
|
|
json_object *json)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
struct pim_ifchannel *ch;
|
|
|
|
struct interface *ifp;
|
|
|
|
time_t now;
|
|
|
|
|
|
|
|
now = pim_time_monotonic_sec();
|
|
|
|
|
2022-03-02 05:50:22 +01:00
|
|
|
if (!json)
|
2022-02-08 18:14:26 +01:00
|
|
|
vty_out(vty,
|
|
|
|
"Interface Address Source Group State Uptime Expire Prune\n");
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
|
|
|
|
if (!pim_sgaddr_match(ch->sg, *sg))
|
|
|
|
continue;
|
2022-03-02 05:50:22 +01:00
|
|
|
|
|
|
|
pim_show_join_helper(vty, pim_ifp, ch, json, now);
|
2022-02-08 18:14:26 +01:00
|
|
|
} /* scan interface channels */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-22 07:58:42 +02:00
|
|
|
static void pim_show_jp_agg_helper(struct interface *ifp,
|
2022-02-08 18:14:26 +01:00
|
|
|
struct pim_neighbor *neigh,
|
2022-08-22 07:58:42 +02:00
|
|
|
struct pim_upstream *up, int is_join,
|
|
|
|
struct ttable *tt)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
2022-08-22 07:58:42 +02:00
|
|
|
ttable_add_row(tt, "%s|%pPAs|%pPAs|%pPAs|%s", ifp->name,
|
|
|
|
&neigh->source_addr, &up->sg.src, &up->sg.grp,
|
|
|
|
is_join ? "J" : "P");
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
|
2022-06-09 09:15:11 +02:00
|
|
|
int pim_show_jp_agg_list_cmd_helper(const char *vrf, struct vty *vty)
|
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
struct pim_instance *pim;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 09:15:11 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
pim_show_jp_agg_list(pim, vty);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-02-08 18:14:26 +01:00
|
|
|
void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
|
|
|
|
{
|
|
|
|
struct interface *ifp;
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
struct listnode *n_node;
|
|
|
|
struct pim_neighbor *neigh;
|
|
|
|
struct listnode *jag_node;
|
|
|
|
struct pim_jp_agg_group *jag;
|
|
|
|
struct listnode *js_node;
|
|
|
|
struct pim_jp_sources *js;
|
2022-08-22 07:58:42 +02:00
|
|
|
struct ttable *tt;
|
|
|
|
char *table;
|
2022-02-08 18:14:26 +01:00
|
|
|
|
2022-08-22 07:58:42 +02:00
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(tt, "Interface|RPF Nbr|Source|Group|State");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, n_node,
|
|
|
|
neigh)) {
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
|
|
|
|
jag_node, jag)) {
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
|
|
|
|
js)) {
|
2022-08-22 07:58:42 +02:00
|
|
|
pim_show_jp_agg_helper(ifp, neigh,
|
2022-02-08 18:14:26 +01:00
|
|
|
js->up,
|
2022-08-22 07:58:42 +02:00
|
|
|
js->is_join, tt);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-22 07:58:42 +02:00
|
|
|
|
|
|
|
/* Dump the generated table. */
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
|
2022-06-09 09:31:33 +02:00
|
|
|
int pim_show_membership_cmd_helper(const char *vrf, struct vty *vty, bool uj)
|
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
|
|
|
pim_show_membership(v->info, vty, uj);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-02-08 18:14:26 +01:00
|
|
|
static void pim_show_membership_helper(struct vty *vty,
|
|
|
|
struct pim_interface *pim_ifp,
|
|
|
|
struct pim_ifchannel *ch,
|
|
|
|
struct json_object *json)
|
|
|
|
{
|
|
|
|
json_object *json_iface = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
json_object_object_get_ex(json, ch->interface->name, &json_iface);
|
|
|
|
if (!json_iface) {
|
|
|
|
json_iface = json_object_new_object();
|
|
|
|
json_object_pim_ifp_add(json_iface, ch->interface);
|
|
|
|
json_object_object_add(json, ch->interface->name, json_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_row = json_object_new_object();
|
|
|
|
json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
|
2022-03-02 07:15:32 +01:00
|
|
|
json_object_string_addf(json_row, "group", "%pPAs", &ch->sg.grp);
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object_string_add(json_row, "localMembership",
|
|
|
|
ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
|
2022-03-02 07:15:32 +01:00
|
|
|
? "NOINFO"
|
|
|
|
: "INCLUDE");
|
|
|
|
json_object_object_addf(json_iface, json_row, "%pPAs", &ch->sg.grp);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
|
|
|
|
{
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
struct pim_ifchannel *ch;
|
|
|
|
struct interface *ifp;
|
|
|
|
enum json_type type;
|
|
|
|
json_object *json = NULL;
|
|
|
|
json_object *json_tmp = NULL;
|
|
|
|
|
|
|
|
json = json_object_new_object();
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
|
|
|
|
pim_show_membership_helper(vty, pim_ifp, ch, json);
|
|
|
|
} /* scan interface channels */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uj) {
|
2022-03-02 07:15:32 +01:00
|
|
|
vty_json(vty, json);
|
2022-02-08 18:14:26 +01:00
|
|
|
} else {
|
|
|
|
vty_out(vty,
|
|
|
|
"Interface Address Source Group Membership\n");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Example of the json data we are traversing
|
|
|
|
*
|
|
|
|
* {
|
|
|
|
* "swp3":{
|
|
|
|
* "name":"swp3",
|
|
|
|
* "state":"up",
|
|
|
|
* "address":"10.1.20.1",
|
|
|
|
* "index":5,
|
|
|
|
* "flagMulticast":true,
|
|
|
|
* "flagBroadcast":true,
|
|
|
|
* "lanDelayEnabled":true,
|
|
|
|
* "226.10.10.10":{
|
|
|
|
* "source":"*",
|
|
|
|
* "group":"226.10.10.10",
|
|
|
|
* "localMembership":"INCLUDE"
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* foreach interface */
|
|
|
|
json_object_object_foreach(json, key, val)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Find all of the keys where the val is an object. In
|
|
|
|
* the example
|
|
|
|
* above the only one is 226.10.10.10
|
|
|
|
*/
|
|
|
|
json_object_object_foreach(val, if_field_key,
|
|
|
|
if_field_val)
|
|
|
|
{
|
|
|
|
type = json_object_get_type(if_field_val);
|
|
|
|
|
|
|
|
if (type == json_type_object) {
|
|
|
|
vty_out(vty, "%-16s ", key);
|
|
|
|
|
|
|
|
json_object_object_get_ex(
|
|
|
|
val, "address", &json_tmp);
|
|
|
|
vty_out(vty, "%-15s ",
|
|
|
|
json_object_get_string(
|
|
|
|
json_tmp));
|
|
|
|
|
|
|
|
json_object_object_get_ex(if_field_val,
|
|
|
|
"source",
|
|
|
|
&json_tmp);
|
|
|
|
vty_out(vty, "%-15s ",
|
|
|
|
json_object_get_string(
|
|
|
|
json_tmp));
|
|
|
|
|
|
|
|
/* Group */
|
|
|
|
vty_out(vty, "%-15s ", if_field_key);
|
|
|
|
|
|
|
|
json_object_object_get_ex(
|
|
|
|
if_field_val, "localMembership",
|
|
|
|
&json_tmp);
|
|
|
|
vty_out(vty, "%-10s\n",
|
|
|
|
json_object_get_string(
|
|
|
|
json_tmp));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-03-02 07:15:32 +01:00
|
|
|
json_object_free(json);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-22 07:35:04 +02:00
|
|
|
static void pim_show_channel_helper(struct pim_instance *pim,
|
2022-02-08 18:14:26 +01:00
|
|
|
struct pim_interface *pim_ifp,
|
|
|
|
struct pim_ifchannel *ch, json_object *json,
|
2022-08-22 07:35:04 +02:00
|
|
|
bool uj, struct ttable *tt)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
|
|
|
struct pim_upstream *up = ch->upstream;
|
|
|
|
json_object *json_group = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
if (uj) {
|
2022-02-25 10:47:35 +01:00
|
|
|
char grp_str[PIM_ADDRSTRLEN];
|
|
|
|
|
|
|
|
snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
|
2022-02-08 18:14:26 +01:00
|
|
|
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, "interface",
|
|
|
|
ch->interface->name);
|
2022-02-25 10:47:35 +01:00
|
|
|
json_object_string_addf(json_row, "source", "%pPAs",
|
|
|
|
&up->sg.src);
|
|
|
|
json_object_string_addf(json_row, "group", "%pPAs",
|
|
|
|
&up->sg.grp);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
if (pim_macro_ch_lost_assert(ch))
|
|
|
|
json_object_boolean_true_add(json_row, "lostAssert");
|
|
|
|
|
|
|
|
if (pim_macro_chisin_joins(ch))
|
|
|
|
json_object_boolean_true_add(json_row, "joins");
|
|
|
|
|
|
|
|
if (pim_macro_chisin_pim_include(ch))
|
|
|
|
json_object_boolean_true_add(json_row, "pimInclude");
|
|
|
|
|
|
|
|
if (pim_upstream_evaluate_join_desired(pim, up))
|
|
|
|
json_object_boolean_true_add(json_row,
|
|
|
|
"evaluateJoinDesired");
|
|
|
|
|
2022-02-25 10:47:35 +01:00
|
|
|
json_object_object_addf(json_group, json_row, "%pPAs",
|
|
|
|
&up->sg.src);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
} else {
|
2022-08-22 07:35:04 +02:00
|
|
|
ttable_add_row(tt, "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s",
|
|
|
|
ch->interface->name, &up->sg.src, &up->sg.grp,
|
|
|
|
pim_macro_ch_lost_assert(ch) ? "yes" : "no",
|
|
|
|
pim_macro_chisin_joins(ch) ? "yes" : "no",
|
|
|
|
pim_macro_chisin_pim_include(ch) ? "yes" : "no",
|
|
|
|
PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
|
|
|
|
? "yes"
|
|
|
|
: "no",
|
|
|
|
pim_upstream_evaluate_join_desired(pim, up)
|
|
|
|
? "yes"
|
|
|
|
: "no");
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
|
|
|
|
{
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
struct pim_ifchannel *ch;
|
|
|
|
struct interface *ifp;
|
2022-08-22 07:35:04 +02:00
|
|
|
struct ttable *tt = NULL;
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object *json = NULL;
|
2022-08-22 07:35:04 +02:00
|
|
|
char *table = NULL;
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
if (uj)
|
|
|
|
json = json_object_new_object();
|
2022-08-22 07:35:04 +02:00
|
|
|
else {
|
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(
|
|
|
|
tt,
|
|
|
|
"Interface|Source|Group|LostAssert|Joins|PimInclude|JoinDesired|EvalJD");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
|
|
|
}
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
/* scan per-interface (S,G) state */
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
|
|
|
|
/* scan all interfaces */
|
2022-08-22 07:35:04 +02:00
|
|
|
pim_show_channel_helper(pim, pim_ifp, ch, json, uj, tt);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
vty_json(vty, json);
|
2022-08-22 07:35:04 +02:00
|
|
|
else {
|
|
|
|
/* Dump the generated table. */
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
|
|
|
}
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
|
2022-06-02 06:54:44 +02:00
|
|
|
int pim_show_channel_cmd_helper(const char *vrf, struct vty *vty, bool uj)
|
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
|
|
|
pim_show_channel(v->info, vty, uj);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-06-09 08:10:22 +02:00
|
|
|
int pim_show_interface_cmd_helper(const char *vrf, struct vty *vty, bool uj,
|
|
|
|
bool mlag, const char *interface)
|
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
json_object *json_parent = NULL;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
|
|
|
|
if (interface)
|
|
|
|
pim_show_interfaces_single(v->info, vty, interface, mlag,
|
|
|
|
json_parent);
|
|
|
|
else
|
|
|
|
pim_show_interfaces(v->info, vty, mlag, json_parent);
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-06-09 08:56:17 +02:00
|
|
|
int pim_show_interface_vrf_all_cmd_helper(struct vty *vty, bool uj, bool mlag,
|
|
|
|
const char *interface)
|
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
json_object *json_parent = NULL;
|
|
|
|
json_object *json_vrf = NULL;
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
|
|
|
|
RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
|
|
|
|
if (!uj)
|
|
|
|
vty_out(vty, "VRF: %s\n", v->name);
|
|
|
|
else
|
|
|
|
json_vrf = json_object_new_object();
|
|
|
|
|
|
|
|
if (interface)
|
|
|
|
pim_show_interfaces_single(v->info, vty, interface,
|
|
|
|
mlag, json_vrf);
|
|
|
|
else
|
|
|
|
pim_show_interfaces(v->info, vty, mlag, json_vrf);
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
json_object_object_add(json_parent, v->name, json_vrf);
|
|
|
|
}
|
|
|
|
if (uj)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-02-08 18:14:26 +01:00
|
|
|
void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
|
2022-02-28 11:28:14 +01:00
|
|
|
json_object *json)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
|
|
|
struct interface *ifp;
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
struct pim_upstream *up;
|
|
|
|
int fhr = 0;
|
|
|
|
int pim_nbrs = 0;
|
|
|
|
int pim_ifchannels = 0;
|
2022-02-28 11:28:14 +01:00
|
|
|
bool uj = true;
|
2022-08-03 11:22:28 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object *json_row = NULL;
|
|
|
|
json_object *json_tmp;
|
|
|
|
|
2022-02-28 11:28:14 +01:00
|
|
|
if (!json) {
|
|
|
|
uj = false;
|
|
|
|
json = json_object_new_object();
|
|
|
|
}
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (mlag == true && pim_ifp->activeactive == false)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pim_nbrs = pim_ifp->pim_neighbor_list->count;
|
|
|
|
pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
|
|
|
|
fhr = 0;
|
|
|
|
|
|
|
|
frr_each (rb_pim_upstream, &pim->upstream_head, up)
|
|
|
|
if (ifp == up->rpf.source_nexthop.interface)
|
|
|
|
if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
|
|
|
|
fhr++;
|
|
|
|
|
|
|
|
json_row = json_object_new_object();
|
|
|
|
json_object_pim_ifp_add(json_row, ifp);
|
|
|
|
json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
|
|
|
|
json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
|
|
|
|
json_object_int_add(json_row, "firstHopRouterCount", fhr);
|
2022-02-28 11:28:14 +01:00
|
|
|
json_object_string_addf(json_row, "pimDesignatedRouter",
|
|
|
|
"%pPAs", &pim_ifp->pim_dr_addr);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
2022-06-08 17:33:32 +02:00
|
|
|
if (!pim_addr_cmp(pim_ifp->pim_dr_addr,
|
|
|
|
pim_ifp->primary_address))
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_row, "pimDesignatedRouterLocal");
|
|
|
|
|
|
|
|
json_object_object_add(json, ifp->name, json_row);
|
|
|
|
}
|
|
|
|
|
2022-02-28 11:28:14 +01:00
|
|
|
if (!uj) {
|
2022-08-03 11:22:28 +02:00
|
|
|
|
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(
|
|
|
|
tt,
|
|
|
|
"Interface|State|Address|PIM Nbrs|PIM DR|FHR|IfChannels");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
json_object_object_foreach(json, key, val)
|
|
|
|
{
|
2022-08-03 11:22:28 +02:00
|
|
|
const char *state, *address, *pimdr;
|
|
|
|
int neighbors, firsthpr, pimifchnl;
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
json_object_object_get_ex(val, "state", &json_tmp);
|
2022-08-03 11:22:28 +02:00
|
|
|
state = json_object_get_string(json_tmp);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
json_object_object_get_ex(val, "address", &json_tmp);
|
2022-08-03 11:22:28 +02:00
|
|
|
address = json_object_get_string(json_tmp);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
json_object_object_get_ex(val, "pimNeighbors",
|
|
|
|
&json_tmp);
|
2022-08-03 11:22:28 +02:00
|
|
|
neighbors = json_object_get_int(json_tmp);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
if (json_object_object_get_ex(
|
|
|
|
val, "pimDesignatedRouterLocal",
|
|
|
|
&json_tmp)) {
|
2022-08-03 11:22:28 +02:00
|
|
|
pimdr = "local";
|
2022-02-08 18:14:26 +01:00
|
|
|
} else {
|
|
|
|
json_object_object_get_ex(
|
|
|
|
val, "pimDesignatedRouter", &json_tmp);
|
2022-08-03 11:22:28 +02:00
|
|
|
pimdr = json_object_get_string(json_tmp);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
json_object_object_get_ex(val, "firstHopRouter",
|
|
|
|
&json_tmp);
|
2022-08-03 11:22:28 +02:00
|
|
|
firsthpr = json_object_get_int(json_tmp);
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
json_object_object_get_ex(val, "pimIfChannels",
|
|
|
|
&json_tmp);
|
2022-08-03 11:22:28 +02:00
|
|
|
pimifchnl = json_object_get_int(json_tmp);
|
|
|
|
|
|
|
|
ttable_add_row(tt, "%s|%s|%s|%d|%s|%d|%d", key, state,
|
|
|
|
address, neighbors, pimdr, firsthpr,
|
|
|
|
pimifchnl);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
pimd, pim6d: deleting the memory malloced for json.
Problem Statement:
=================
2022-08-18 04:57:32,376 - ERROR: Found memory leak in daemon pimd
2022-08-18 04:57:32,377 - ERROR: ==12100== 18,978 (144 direct, 18,834 indirect) bytes in 2 blocks are definitely lost in loss record 45 of 45
2022-08-18 04:57:32,377 - ERROR: ==12100== at 0x4C31FAC: calloc (vg_replace_malloc.c:762)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x532F51F: json_object_new_object (in /lib/x86_64-linux-gnu/libjson-c.so.3.0.1)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x128B5C: pim_show_interfaces (pim_cmd_common.c:3395)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x15A86B: show_ip_pim_interface_magic (pim_cmd.c:3127)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x15A86B: show_ip_pim_interface (pim_cmd_clippy.c:324)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x4E672B2: cmd_execute_command_real.isra.2 (command.c:1005)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x4E696FE: cmd_execute_command (command.c:1064)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x4E698F1: cmd_execute (command.c:1227)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x4EBC814: vty_command (vty.c:530)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x4EBC9EF: vty_execute (vty.c:1295)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x4EBF1F7: vtysh_read (vty.c:2142)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x4EB739B: thread_call (thread.c:1692)
2022-08-18 04:57:32,377 - ERROR: ==12100== by 0x4E85B17: frr_run (libfrr.c:1068)
2022-08-18 04:57:32,377 - ERROR: ==12100==
Signed-off-by: Abhishek N R <abnr@vmware.com>
2022-08-29 13:50:26 +02:00
|
|
|
json_object_free(json);
|
2022-08-03 11:22:28 +02:00
|
|
|
|
|
|
|
/* Dump the generated table. */
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
|
|
|
|
ttable_del(tt);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-28 11:28:14 +01:00
|
|
|
void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty,
|
|
|
|
const char *ifname, bool mlag,
|
|
|
|
json_object *json)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
|
|
|
pim_addr ifaddr;
|
|
|
|
struct interface *ifp;
|
|
|
|
struct listnode *neighnode;
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
struct pim_neighbor *neigh;
|
|
|
|
struct pim_upstream *up;
|
|
|
|
time_t now;
|
2022-02-28 11:28:14 +01:00
|
|
|
char dr_str[PIM_ADDRSTRLEN];
|
2022-02-08 18:14:26 +01:00
|
|
|
char dr_uptime[10];
|
|
|
|
char expire[10];
|
2022-02-28 11:28:14 +01:00
|
|
|
char grp_str[PIM_ADDRSTRLEN];
|
2022-02-08 18:14:26 +01:00
|
|
|
char hello_period[10];
|
|
|
|
char hello_timer[10];
|
2022-02-28 11:28:14 +01:00
|
|
|
char neigh_src_str[PIM_ADDRSTRLEN];
|
|
|
|
char src_str[PIM_ADDRSTRLEN];
|
2022-02-08 18:14:26 +01:00
|
|
|
char stat_uptime[10];
|
|
|
|
char uptime[10];
|
|
|
|
int found_ifname = 0;
|
|
|
|
int print_header;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
json_object *json_pim_neighbor = NULL;
|
|
|
|
json_object *json_pim_neighbors = NULL;
|
|
|
|
json_object *json_group = NULL;
|
|
|
|
json_object *json_group_source = NULL;
|
|
|
|
json_object *json_fhr_sources = NULL;
|
|
|
|
struct pim_secondary_addr *sec_addr;
|
|
|
|
struct listnode *sec_node;
|
|
|
|
|
|
|
|
now = pim_time_monotonic_sec();
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (mlag == true && pim_ifp->activeactive == false)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
found_ifname = 1;
|
|
|
|
ifaddr = pim_ifp->primary_address;
|
2022-02-28 11:28:14 +01:00
|
|
|
snprintfrr(dr_str, sizeof(dr_str), "%pPAs",
|
|
|
|
&pim_ifp->pim_dr_addr);
|
2022-02-08 18:14:26 +01:00
|
|
|
pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
|
|
|
|
pim_ifp->pim_dr_election_last);
|
|
|
|
pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
|
|
|
|
pim_ifp->t_pim_hello_timer);
|
|
|
|
pim_time_mmss(hello_period, sizeof(hello_period),
|
|
|
|
pim_ifp->pim_hello_period);
|
|
|
|
pim_time_uptime(stat_uptime, sizeof(stat_uptime),
|
|
|
|
now - pim_ifp->pim_ifstat_start);
|
|
|
|
|
2022-02-28 11:28:14 +01:00
|
|
|
if (json) {
|
2022-02-08 18:14:26 +01:00
|
|
|
json_row = json_object_new_object();
|
|
|
|
json_object_pim_ifp_add(json_row, ifp);
|
|
|
|
|
2022-02-28 11:28:14 +01:00
|
|
|
if (!pim_addr_is_any(pim_ifp->update_source)) {
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object_string_addf(
|
2022-02-28 11:28:14 +01:00
|
|
|
json_row, "useSource", "%pPAs",
|
2022-02-08 18:14:26 +01:00
|
|
|
&pim_ifp->update_source);
|
|
|
|
}
|
|
|
|
if (pim_ifp->sec_addr_list) {
|
|
|
|
json_object *sec_list = NULL;
|
|
|
|
|
|
|
|
sec_list = json_object_new_array();
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(
|
|
|
|
pim_ifp->sec_addr_list, sec_node,
|
|
|
|
sec_addr)) {
|
|
|
|
json_object_array_add(
|
|
|
|
sec_list,
|
2022-02-28 11:28:14 +01:00
|
|
|
json_object_new_stringf(
|
|
|
|
"%pFXh",
|
|
|
|
&sec_addr->addr));
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
json_object_object_add(json_row,
|
|
|
|
"secondaryAddressList",
|
|
|
|
sec_list);
|
|
|
|
}
|
|
|
|
|
2022-04-07 09:43:20 +02:00
|
|
|
if (pim_ifp->pim_passive_enable)
|
|
|
|
json_object_boolean_true_add(json_row,
|
|
|
|
"passive");
|
|
|
|
|
2022-02-08 18:14:26 +01:00
|
|
|
/* PIM neighbors */
|
|
|
|
if (pim_ifp->pim_neighbor_list->count) {
|
|
|
|
json_pim_neighbors = json_object_new_object();
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(
|
|
|
|
pim_ifp->pim_neighbor_list,
|
|
|
|
neighnode, neigh)) {
|
|
|
|
json_pim_neighbor =
|
|
|
|
json_object_new_object();
|
2022-02-28 11:28:14 +01:00
|
|
|
snprintfrr(neigh_src_str,
|
|
|
|
sizeof(neigh_src_str),
|
|
|
|
"%pPAs",
|
|
|
|
&neigh->source_addr);
|
2022-02-08 18:14:26 +01:00
|
|
|
pim_time_uptime(uptime, sizeof(uptime),
|
|
|
|
now - neigh->creation);
|
|
|
|
pim_time_timer_to_hhmmss(
|
|
|
|
expire, sizeof(expire),
|
|
|
|
neigh->t_expire_timer);
|
|
|
|
|
|
|
|
json_object_string_add(
|
|
|
|
json_pim_neighbor, "address",
|
|
|
|
neigh_src_str);
|
|
|
|
json_object_string_add(
|
|
|
|
json_pim_neighbor, "upTime",
|
|
|
|
uptime);
|
|
|
|
json_object_string_add(
|
|
|
|
json_pim_neighbor, "holdtime",
|
|
|
|
expire);
|
|
|
|
|
|
|
|
json_object_object_add(
|
|
|
|
json_pim_neighbors,
|
|
|
|
neigh_src_str,
|
|
|
|
json_pim_neighbor);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_object_object_add(json_row, "neighbors",
|
|
|
|
json_pim_neighbors);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_object_string_add(json_row, "drAddress", dr_str);
|
|
|
|
json_object_int_add(json_row, "drPriority",
|
|
|
|
pim_ifp->pim_dr_priority);
|
|
|
|
json_object_string_add(json_row, "drUptime", dr_uptime);
|
|
|
|
json_object_int_add(json_row, "drElections",
|
|
|
|
pim_ifp->pim_dr_election_count);
|
|
|
|
json_object_int_add(json_row, "drChanges",
|
|
|
|
pim_ifp->pim_dr_election_changes);
|
|
|
|
|
|
|
|
/* FHR */
|
|
|
|
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
|
|
|
|
if (ifp != up->rpf.source_nexthop.interface)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!json_fhr_sources)
|
|
|
|
json_fhr_sources =
|
|
|
|
json_object_new_object();
|
|
|
|
|
|
|
|
snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
|
|
|
|
&up->sg.grp);
|
|
|
|
snprintfrr(src_str, sizeof(src_str), "%pPAs",
|
|
|
|
&up->sg.src);
|
|
|
|
pim_time_uptime(uptime, sizeof(uptime),
|
|
|
|
now - up->state_transition);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Does this group live in json_fhr_sources?
|
|
|
|
* If not create it.
|
|
|
|
*/
|
|
|
|
json_object_object_get_ex(json_fhr_sources,
|
|
|
|
grp_str, &json_group);
|
|
|
|
|
|
|
|
if (!json_group) {
|
|
|
|
json_group = json_object_new_object();
|
|
|
|
json_object_object_add(json_fhr_sources,
|
|
|
|
grp_str,
|
|
|
|
json_group);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_group_source = json_object_new_object();
|
|
|
|
json_object_string_add(json_group_source,
|
|
|
|
"source", src_str);
|
|
|
|
json_object_string_add(json_group_source,
|
|
|
|
"group", grp_str);
|
|
|
|
json_object_string_add(json_group_source,
|
|
|
|
"upTime", uptime);
|
|
|
|
json_object_object_add(json_group, src_str,
|
|
|
|
json_group_source);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json_fhr_sources) {
|
|
|
|
json_object_object_add(json_row,
|
|
|
|
"firstHopRouter",
|
|
|
|
json_fhr_sources);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_object_int_add(json_row, "helloPeriod",
|
|
|
|
pim_ifp->pim_hello_period);
|
|
|
|
json_object_int_add(json_row, "holdTime",
|
|
|
|
PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
|
|
|
|
json_object_string_add(json_row, "helloTimer",
|
|
|
|
hello_timer);
|
|
|
|
json_object_string_add(json_row, "helloStatStart",
|
|
|
|
stat_uptime);
|
|
|
|
json_object_int_add(json_row, "helloReceived",
|
|
|
|
pim_ifp->pim_ifstat_hello_recv);
|
|
|
|
json_object_int_add(json_row, "helloReceivedFailed",
|
|
|
|
pim_ifp->pim_ifstat_hello_recvfail);
|
|
|
|
json_object_int_add(json_row, "helloSend",
|
|
|
|
pim_ifp->pim_ifstat_hello_sent);
|
|
|
|
json_object_int_add(json_row, "hellosendFailed",
|
|
|
|
pim_ifp->pim_ifstat_hello_sendfail);
|
|
|
|
json_object_int_add(json_row, "helloGenerationId",
|
|
|
|
pim_ifp->pim_generation_id);
|
|
|
|
|
|
|
|
json_object_int_add(
|
|
|
|
json_row, "effectivePropagationDelay",
|
|
|
|
pim_if_effective_propagation_delay_msec(ifp));
|
|
|
|
json_object_int_add(
|
|
|
|
json_row, "effectiveOverrideInterval",
|
|
|
|
pim_if_effective_override_interval_msec(ifp));
|
|
|
|
json_object_int_add(
|
|
|
|
json_row, "joinPruneOverrideInterval",
|
|
|
|
pim_if_jp_override_interval_msec(ifp));
|
|
|
|
|
|
|
|
json_object_int_add(
|
|
|
|
json_row, "propagationDelay",
|
|
|
|
pim_ifp->pim_propagation_delay_msec);
|
|
|
|
json_object_int_add(
|
|
|
|
json_row, "propagationDelayHighest",
|
|
|
|
pim_ifp->pim_neighbors_highest_propagation_delay_msec);
|
|
|
|
json_object_int_add(
|
|
|
|
json_row, "overrideInterval",
|
|
|
|
pim_ifp->pim_override_interval_msec);
|
|
|
|
json_object_int_add(
|
|
|
|
json_row, "overrideIntervalHighest",
|
|
|
|
pim_ifp->pim_neighbors_highest_override_interval_msec);
|
|
|
|
if (pim_ifp->bsm_enable)
|
|
|
|
json_object_boolean_true_add(json_row,
|
|
|
|
"bsmEnabled");
|
|
|
|
if (pim_ifp->ucast_bsm_accept)
|
|
|
|
json_object_boolean_true_add(json_row,
|
|
|
|
"ucastBsmEnabled");
|
|
|
|
json_object_object_add(json, ifp->name, json_row);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
vty_out(vty, "Interface : %s\n", ifp->name);
|
|
|
|
vty_out(vty, "State : %s\n",
|
|
|
|
if_is_up(ifp) ? "up" : "down");
|
2022-02-28 11:28:14 +01:00
|
|
|
if (!pim_addr_is_any(pim_ifp->update_source)) {
|
|
|
|
vty_out(vty, "Use Source : %pPAs\n",
|
2022-02-08 18:14:26 +01:00
|
|
|
&pim_ifp->update_source);
|
|
|
|
}
|
|
|
|
if (pim_ifp->sec_addr_list) {
|
2022-02-28 11:28:14 +01:00
|
|
|
vty_out(vty, "Address : %pPAs (primary)\n",
|
2022-02-08 18:14:26 +01:00
|
|
|
&ifaddr);
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(
|
|
|
|
pim_ifp->sec_addr_list, sec_node,
|
|
|
|
sec_addr))
|
|
|
|
vty_out(vty, " %pFX\n",
|
|
|
|
&sec_addr->addr);
|
|
|
|
} else {
|
2022-02-28 11:28:14 +01:00
|
|
|
vty_out(vty, "Address : %pPAs\n", &ifaddr);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
2022-04-07 09:43:20 +02:00
|
|
|
|
|
|
|
if (pim_ifp->pim_passive_enable)
|
|
|
|
vty_out(vty, "Passive : %s\n",
|
|
|
|
(pim_ifp->pim_passive_enable) ? "yes"
|
|
|
|
: "no");
|
|
|
|
|
2022-02-08 18:14:26 +01:00
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
/* PIM neighbors */
|
|
|
|
print_header = 1;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
|
|
|
|
neighnode, neigh)) {
|
|
|
|
|
|
|
|
if (print_header) {
|
|
|
|
vty_out(vty, "PIM Neighbors\n");
|
|
|
|
vty_out(vty, "-------------\n");
|
|
|
|
print_header = 0;
|
|
|
|
}
|
|
|
|
|
2022-02-28 11:28:14 +01:00
|
|
|
snprintfrr(neigh_src_str, sizeof(neigh_src_str),
|
|
|
|
"%pPAs", &neigh->source_addr);
|
2022-02-08 18:14:26 +01:00
|
|
|
pim_time_uptime(uptime, sizeof(uptime),
|
|
|
|
now - neigh->creation);
|
|
|
|
pim_time_timer_to_hhmmss(expire, sizeof(expire),
|
|
|
|
neigh->t_expire_timer);
|
|
|
|
vty_out(vty,
|
|
|
|
"%-15s : up for %s, holdtime expires in %s\n",
|
|
|
|
neigh_src_str, uptime, expire);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!print_header) {
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
vty_out(vty, "Designated Router\n");
|
|
|
|
vty_out(vty, "-----------------\n");
|
|
|
|
vty_out(vty, "Address : %s\n", dr_str);
|
|
|
|
vty_out(vty, "Priority : %u(%d)\n",
|
|
|
|
pim_ifp->pim_dr_priority,
|
|
|
|
pim_ifp->pim_dr_num_nondrpri_neighbors);
|
|
|
|
vty_out(vty, "Uptime : %s\n", dr_uptime);
|
|
|
|
vty_out(vty, "Elections : %d\n",
|
|
|
|
pim_ifp->pim_dr_election_count);
|
|
|
|
vty_out(vty, "Changes : %d\n",
|
|
|
|
pim_ifp->pim_dr_election_changes);
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
/* FHR */
|
|
|
|
print_header = 1;
|
|
|
|
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
|
|
|
|
if (!up->rpf.source_nexthop.interface)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (strcmp(ifp->name,
|
|
|
|
up->rpf.source_nexthop
|
2022-02-28 11:28:14 +01:00
|
|
|
.interface->name) != 0)
|
2022-02-08 18:14:26 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (print_header) {
|
|
|
|
vty_out(vty,
|
|
|
|
"FHR - First Hop Router\n");
|
|
|
|
vty_out(vty,
|
|
|
|
"----------------------\n");
|
|
|
|
print_header = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pim_time_uptime(uptime, sizeof(uptime),
|
|
|
|
now - up->state_transition);
|
|
|
|
vty_out(vty,
|
|
|
|
"%pPAs : %pPAs is a source, uptime is %s\n",
|
|
|
|
&up->sg.grp, &up->sg.src, uptime);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!print_header) {
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
vty_out(vty, "Hellos\n");
|
|
|
|
vty_out(vty, "------\n");
|
|
|
|
vty_out(vty, "Period : %d\n",
|
|
|
|
pim_ifp->pim_hello_period);
|
|
|
|
vty_out(vty, "HoldTime : %d\n",
|
|
|
|
PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
|
|
|
|
vty_out(vty, "Timer : %s\n", hello_timer);
|
|
|
|
vty_out(vty, "StatStart : %s\n", stat_uptime);
|
|
|
|
vty_out(vty, "Receive : %d\n",
|
|
|
|
pim_ifp->pim_ifstat_hello_recv);
|
|
|
|
vty_out(vty, "Receive Failed : %d\n",
|
|
|
|
pim_ifp->pim_ifstat_hello_recvfail);
|
|
|
|
vty_out(vty, "Send : %d\n",
|
|
|
|
pim_ifp->pim_ifstat_hello_sent);
|
|
|
|
vty_out(vty, "Send Failed : %d\n",
|
|
|
|
pim_ifp->pim_ifstat_hello_sendfail);
|
|
|
|
vty_out(vty, "Generation ID : %08x\n",
|
|
|
|
pim_ifp->pim_generation_id);
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
pim_print_ifp_flags(vty, ifp);
|
|
|
|
|
|
|
|
vty_out(vty, "Join Prune Interval\n");
|
|
|
|
vty_out(vty, "-------------------\n");
|
|
|
|
vty_out(vty, "LAN Delay : %s\n",
|
|
|
|
pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
|
|
|
|
vty_out(vty, "Effective Propagation Delay : %d msec\n",
|
|
|
|
pim_if_effective_propagation_delay_msec(ifp));
|
|
|
|
vty_out(vty, "Effective Override Interval : %d msec\n",
|
|
|
|
pim_if_effective_override_interval_msec(ifp));
|
|
|
|
vty_out(vty, "Join Prune Override Interval : %d msec\n",
|
|
|
|
pim_if_jp_override_interval_msec(ifp));
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
vty_out(vty, "LAN Prune Delay\n");
|
|
|
|
vty_out(vty, "---------------\n");
|
|
|
|
vty_out(vty, "Propagation Delay : %d msec\n",
|
|
|
|
pim_ifp->pim_propagation_delay_msec);
|
|
|
|
vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
|
|
|
|
pim_ifp->pim_neighbors_highest_propagation_delay_msec);
|
|
|
|
vty_out(vty, "Override Interval : %d msec\n",
|
|
|
|
pim_ifp->pim_override_interval_msec);
|
|
|
|
vty_out(vty, "Override Interval (Highest) : %d msec\n",
|
|
|
|
pim_ifp->pim_neighbors_highest_override_interval_msec);
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
vty_out(vty, "BSM Status\n");
|
|
|
|
vty_out(vty, "----------\n");
|
|
|
|
vty_out(vty, "Bsm Enabled : %s\n",
|
|
|
|
pim_ifp->bsm_enable ? "yes" : "no");
|
|
|
|
vty_out(vty, "Unicast Bsm Enabled : %s\n",
|
|
|
|
pim_ifp->ucast_bsm_accept ? "yes" : "no");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-28 11:28:14 +01:00
|
|
|
if (!found_ifname)
|
2022-02-08 18:14:26 +01:00
|
|
|
vty_out(vty, "%% No such interface\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
|
|
|
|
bool uj)
|
|
|
|
{
|
|
|
|
struct pim_ssm *ssm = pim->ssm_info;
|
|
|
|
const char *range_str =
|
|
|
|
ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
|
|
|
|
|
|
|
|
if (uj) {
|
|
|
|
json_object *json;
|
|
|
|
|
|
|
|
json = json_object_new_object();
|
|
|
|
json_object_string_add(json, "ssmGroups", range_str);
|
|
|
|
vty_json(vty, json);
|
|
|
|
} else
|
|
|
|
vty_out(vty, "SSM group range : %s\n", range_str);
|
|
|
|
}
|
|
|
|
|
2022-06-13 10:49:03 +02:00
|
|
|
struct vty_pnc_cache_walk_data {
|
2022-02-08 18:14:26 +01:00
|
|
|
struct vty *vty;
|
|
|
|
struct pim_instance *pim;
|
|
|
|
};
|
|
|
|
|
2022-06-13 10:49:03 +02:00
|
|
|
struct json_pnc_cache_walk_data {
|
|
|
|
json_object *json_obj;
|
|
|
|
struct pim_instance *pim;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
|
|
|
struct pim_nexthop_cache *pnc = bucket->data;
|
2022-06-13 10:49:03 +02:00
|
|
|
struct vty_pnc_cache_walk_data *cwd = arg;
|
2022-02-08 18:14:26 +01:00
|
|
|
struct vty *vty = cwd->vty;
|
|
|
|
struct pim_instance *pim = cwd->pim;
|
|
|
|
struct nexthop *nh_node = NULL;
|
|
|
|
ifindex_t first_ifindex;
|
|
|
|
struct interface *ifp = NULL;
|
|
|
|
|
|
|
|
for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
|
|
|
|
first_ifindex = nh_node->ifindex;
|
2022-06-13 10:49:03 +02:00
|
|
|
|
2022-02-08 18:14:26 +01:00
|
|
|
ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
|
|
|
|
|
2022-04-27 10:55:57 +02:00
|
|
|
vty_out(vty, "%-15pPA ", &pnc->rpf.rpf_addr);
|
2022-02-08 18:14:26 +01:00
|
|
|
vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
|
2022-06-13 10:49:03 +02:00
|
|
|
#if PIM_IPV == 4
|
2022-02-08 18:14:26 +01:00
|
|
|
vty_out(vty, "%pI4 ", &nh_node->gate.ipv4);
|
2022-06-13 10:49:03 +02:00
|
|
|
#else
|
|
|
|
vty_out(vty, "%pI6 ", &nh_node->gate.ipv6);
|
|
|
|
#endif
|
2022-02-08 18:14:26 +01:00
|
|
|
vty_out(vty, "\n");
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-06-13 10:49:03 +02:00
|
|
|
static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet,
|
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
struct pim_nexthop_cache *pnc = backet->data;
|
|
|
|
struct json_pnc_cache_walk_data *cwd = arg;
|
|
|
|
struct pim_instance *pim = cwd->pim;
|
|
|
|
struct nexthop *nh_node = NULL;
|
|
|
|
ifindex_t first_ifindex;
|
|
|
|
struct interface *ifp = NULL;
|
|
|
|
char addr_str[PIM_ADDRSTRLEN];
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
json_object *json_ifp = NULL;
|
|
|
|
json_object *json_arr = NULL;
|
|
|
|
|
|
|
|
for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
|
|
|
|
first_ifindex = nh_node->ifindex;
|
|
|
|
ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
|
2022-04-27 10:55:57 +02:00
|
|
|
snprintfrr(addr_str, sizeof(addr_str), "%pPA",
|
|
|
|
&pnc->rpf.rpf_addr);
|
2022-06-13 10:49:03 +02:00
|
|
|
json_object_object_get_ex(cwd->json_obj, addr_str, &json_row);
|
|
|
|
if (!json_row) {
|
|
|
|
json_row = json_object_new_object();
|
2022-04-27 10:55:57 +02:00
|
|
|
json_object_string_addf(json_row, "address", "%pPA",
|
|
|
|
&pnc->rpf.rpf_addr);
|
|
|
|
json_object_object_addf(cwd->json_obj, json_row, "%pPA",
|
|
|
|
&pnc->rpf.rpf_addr);
|
2022-06-13 10:49:03 +02:00
|
|
|
json_arr = json_object_new_array();
|
|
|
|
json_object_object_add(json_row, "nexthops", json_arr);
|
|
|
|
}
|
|
|
|
json_ifp = json_object_new_object();
|
|
|
|
json_object_string_add(json_ifp, "interface",
|
|
|
|
ifp ? ifp->name : "NULL");
|
|
|
|
#if PIM_IPV == 4
|
|
|
|
json_object_string_addf(json_ifp, "nexthop", "%pI4",
|
|
|
|
&nh_node->gate.ipv4);
|
|
|
|
#else
|
|
|
|
json_object_string_addf(json_ifp, "nexthop", "%pI6",
|
|
|
|
&nh_node->gate.ipv6);
|
|
|
|
#endif
|
|
|
|
json_object_array_add(json_arr, json_ifp);
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-06-09 13:22:42 +02:00
|
|
|
int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty,
|
|
|
|
pim_addr source, pim_addr group)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
pim_addr vif_source;
|
|
|
|
struct prefix grp;
|
|
|
|
struct pim_nexthop nexthop;
|
|
|
|
struct vrf *v;
|
|
|
|
char grp_str[PREFIX_STRLEN];
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
|
|
|
#if PIM_IPV == 4
|
|
|
|
if (pim_is_group_224_4(source)) {
|
|
|
|
vty_out(vty,
|
|
|
|
"Invalid argument. Expected Valid Source Address.\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pim_is_group_224_4(group)) {
|
|
|
|
vty_out(vty,
|
|
|
|
"Invalid argument. Expected Valid Multicast Group Address.\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!pim_rp_set_upstream_addr(v->info, &vif_source, source, group))
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
|
|
|
|
pim_addr_to_prefix(&grp, group);
|
|
|
|
memset(&nexthop, 0, sizeof(nexthop));
|
|
|
|
|
2022-04-27 10:55:57 +02:00
|
|
|
result =
|
|
|
|
pim_ecmp_nexthop_lookup(v->info, &nexthop, vif_source, &grp, 0);
|
2022-06-09 13:22:42 +02:00
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
vty_out(vty,
|
|
|
|
"Nexthop Lookup failed, no usable routes returned.\n");
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str));
|
|
|
|
|
|
|
|
vty_out(vty, "Group %s --- Nexthop %pPAs Interface %s\n", grp_str,
|
|
|
|
&nexthop.mrib_nexthop_addr, nexthop.interface->name);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-06-13 10:49:03 +02:00
|
|
|
int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty, bool uj)
|
2022-06-09 12:23:28 +02:00
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
2022-06-13 10:49:03 +02:00
|
|
|
pim_show_nexthop(v->info, vty, uj);
|
2022-06-09 12:23:28 +02:00
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-06-13 10:49:03 +02:00
|
|
|
void pim_show_nexthop(struct pim_instance *pim, struct vty *vty, bool uj)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
2022-06-13 10:49:03 +02:00
|
|
|
struct vty_pnc_cache_walk_data cwd;
|
|
|
|
struct json_pnc_cache_walk_data jcwd;
|
2022-02-08 18:14:26 +01:00
|
|
|
|
|
|
|
cwd.vty = vty;
|
|
|
|
cwd.pim = pim;
|
2022-06-13 10:49:03 +02:00
|
|
|
jcwd.pim = pim;
|
2022-02-08 18:14:26 +01:00
|
|
|
|
2022-06-13 10:49:03 +02:00
|
|
|
if (uj) {
|
|
|
|
jcwd.json_obj = json_object_new_object();
|
|
|
|
} else {
|
|
|
|
vty_out(vty, "Number of registered addresses: %lu\n",
|
|
|
|
pim->rpf_hash->count);
|
|
|
|
vty_out(vty, "Address Interface Nexthop\n");
|
|
|
|
vty_out(vty, "---------------------------------------------\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uj) {
|
|
|
|
hash_walk(pim->rpf_hash, pim_print_json_pnc_cache_walkcb,
|
|
|
|
&jcwd);
|
|
|
|
vty_json(vty, jcwd.json_obj);
|
|
|
|
} else
|
|
|
|
hash_walk(pim->rpf_hash, pim_print_vty_pnc_cache_walkcb, &cwd);
|
2022-02-08 18:14:26 +01:00
|
|
|
}
|
|
|
|
|
2022-06-09 10:34:06 +02:00
|
|
|
int pim_show_neighbors_cmd_helper(const char *vrf, struct vty *vty,
|
|
|
|
const char *json, const char *interface)
|
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
json_object *json_parent = NULL;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
|
|
|
|
if (interface)
|
|
|
|
pim_show_neighbors_single(v->info, vty, interface, json_parent);
|
|
|
|
else
|
|
|
|
pim_show_neighbors(v->info, vty, json_parent);
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-06-09 11:36:08 +02:00
|
|
|
int pim_show_neighbors_vrf_all_cmd_helper(struct vty *vty, const char *json,
|
|
|
|
const char *interface)
|
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
json_object *json_parent = NULL;
|
|
|
|
json_object *json_vrf = NULL;
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
|
|
|
|
if (!json)
|
|
|
|
vty_out(vty, "VRF: %s\n", v->name);
|
|
|
|
else
|
|
|
|
json_vrf = json_object_new_object();
|
|
|
|
|
|
|
|
if (interface)
|
|
|
|
pim_show_neighbors_single(v->info, vty, interface,
|
|
|
|
json_vrf);
|
|
|
|
else
|
|
|
|
pim_show_neighbors(v->info, vty, json_vrf);
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_object_object_add(json_parent, v->name, json_vrf);
|
|
|
|
}
|
|
|
|
if (json)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-02-08 18:14:26 +01:00
|
|
|
void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
|
|
|
|
const char *neighbor, json_object *json)
|
|
|
|
{
|
|
|
|
struct listnode *neighnode;
|
|
|
|
struct interface *ifp;
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
struct pim_neighbor *neigh;
|
|
|
|
time_t now;
|
|
|
|
int found_neighbor = 0;
|
|
|
|
int option_address_list;
|
|
|
|
int option_dr_priority;
|
|
|
|
int option_generation_id;
|
|
|
|
int option_holdtime;
|
|
|
|
int option_lan_prune_delay;
|
|
|
|
int option_t_bit;
|
|
|
|
char uptime[10];
|
|
|
|
char expire[10];
|
|
|
|
char neigh_src_str[PIM_ADDRSTRLEN];
|
|
|
|
|
|
|
|
json_object *json_ifp = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
now = pim_time_monotonic_sec();
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pim_ifp->pim_sock_fd < 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
|
|
|
|
neigh)) {
|
|
|
|
snprintfrr(neigh_src_str, sizeof(neigh_src_str),
|
|
|
|
"%pPAs", &neigh->source_addr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The user can specify either the interface name or the
|
|
|
|
* PIM neighbor IP.
|
|
|
|
* If this pim_ifp matches neither then skip.
|
|
|
|
*/
|
|
|
|
if (strcmp(neighbor, "detail") &&
|
|
|
|
strcmp(neighbor, ifp->name) &&
|
|
|
|
strcmp(neighbor, neigh_src_str))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
found_neighbor = 1;
|
|
|
|
pim_time_uptime(uptime, sizeof(uptime),
|
|
|
|
now - neigh->creation);
|
|
|
|
pim_time_timer_to_hhmmss(expire, sizeof(expire),
|
|
|
|
neigh->t_expire_timer);
|
|
|
|
|
|
|
|
option_address_list = 0;
|
|
|
|
option_dr_priority = 0;
|
|
|
|
option_generation_id = 0;
|
|
|
|
option_holdtime = 0;
|
|
|
|
option_lan_prune_delay = 0;
|
|
|
|
option_t_bit = 0;
|
|
|
|
|
|
|
|
if (PIM_OPTION_IS_SET(neigh->hello_options,
|
|
|
|
PIM_OPTION_MASK_ADDRESS_LIST))
|
|
|
|
option_address_list = 1;
|
|
|
|
|
|
|
|
if (PIM_OPTION_IS_SET(neigh->hello_options,
|
|
|
|
PIM_OPTION_MASK_DR_PRIORITY))
|
|
|
|
option_dr_priority = 1;
|
|
|
|
|
|
|
|
if (PIM_OPTION_IS_SET(neigh->hello_options,
|
|
|
|
PIM_OPTION_MASK_GENERATION_ID))
|
|
|
|
option_generation_id = 1;
|
|
|
|
|
|
|
|
if (PIM_OPTION_IS_SET(neigh->hello_options,
|
|
|
|
PIM_OPTION_MASK_HOLDTIME))
|
|
|
|
option_holdtime = 1;
|
|
|
|
|
|
|
|
if (PIM_OPTION_IS_SET(neigh->hello_options,
|
|
|
|
PIM_OPTION_MASK_LAN_PRUNE_DELAY))
|
|
|
|
option_lan_prune_delay = 1;
|
|
|
|
|
|
|
|
if (PIM_OPTION_IS_SET(
|
|
|
|
neigh->hello_options,
|
|
|
|
PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
|
|
|
|
option_t_bit = 1;
|
|
|
|
|
|
|
|
if (json) {
|
|
|
|
|
|
|
|
/* Does this ifp live in json? If not create it
|
|
|
|
*/
|
|
|
|
json_object_object_get_ex(json, ifp->name,
|
|
|
|
&json_ifp);
|
|
|
|
|
|
|
|
if (!json_ifp) {
|
|
|
|
json_ifp = json_object_new_object();
|
|
|
|
json_object_pim_ifp_add(json_ifp, ifp);
|
|
|
|
json_object_object_add(json, ifp->name,
|
|
|
|
json_ifp);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_row = json_object_new_object();
|
|
|
|
json_object_string_add(json_row, "interface",
|
|
|
|
ifp->name);
|
|
|
|
json_object_string_add(json_row, "address",
|
|
|
|
neigh_src_str);
|
|
|
|
json_object_string_add(json_row, "upTime",
|
|
|
|
uptime);
|
|
|
|
json_object_string_add(json_row, "holdtime",
|
|
|
|
expire);
|
|
|
|
json_object_int_add(json_row, "drPriority",
|
|
|
|
neigh->dr_priority);
|
|
|
|
json_object_int_add(json_row, "generationId",
|
|
|
|
neigh->generation_id);
|
|
|
|
|
|
|
|
if (option_address_list)
|
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_row,
|
|
|
|
"helloOptionAddressList");
|
|
|
|
|
|
|
|
if (option_dr_priority)
|
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_row,
|
|
|
|
"helloOptionDrPriority");
|
|
|
|
|
|
|
|
if (option_generation_id)
|
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_row,
|
|
|
|
"helloOptionGenerationId");
|
|
|
|
|
|
|
|
if (option_holdtime)
|
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_row,
|
|
|
|
"helloOptionHoldtime");
|
|
|
|
|
|
|
|
if (option_lan_prune_delay)
|
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_row,
|
|
|
|
"helloOptionLanPruneDelay");
|
|
|
|
|
|
|
|
if (option_t_bit)
|
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_row, "helloOptionTBit");
|
|
|
|
|
|
|
|
json_object_object_add(json_ifp, neigh_src_str,
|
|
|
|
json_row);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
vty_out(vty, "Interface : %s\n", ifp->name);
|
|
|
|
vty_out(vty, "Neighbor : %s\n", neigh_src_str);
|
|
|
|
vty_out(vty,
|
|
|
|
" Uptime : %s\n",
|
|
|
|
uptime);
|
|
|
|
vty_out(vty,
|
|
|
|
" Holdtime : %s\n",
|
|
|
|
expire);
|
|
|
|
vty_out(vty,
|
|
|
|
" DR Priority : %d\n",
|
|
|
|
neigh->dr_priority);
|
|
|
|
vty_out(vty,
|
|
|
|
" Generation ID : %08x\n",
|
|
|
|
neigh->generation_id);
|
|
|
|
vty_out(vty,
|
|
|
|
" Override Interval (msec) : %d\n",
|
|
|
|
neigh->override_interval_msec);
|
|
|
|
vty_out(vty,
|
|
|
|
" Propagation Delay (msec) : %d\n",
|
|
|
|
neigh->propagation_delay_msec);
|
|
|
|
vty_out(vty,
|
|
|
|
" Hello Option - Address List : %s\n",
|
|
|
|
option_address_list ? "yes" : "no");
|
|
|
|
vty_out(vty,
|
|
|
|
" Hello Option - DR Priority : %s\n",
|
|
|
|
option_dr_priority ? "yes" : "no");
|
|
|
|
vty_out(vty,
|
|
|
|
" Hello Option - Generation ID : %s\n",
|
|
|
|
option_generation_id ? "yes" : "no");
|
|
|
|
vty_out(vty,
|
|
|
|
" Hello Option - Holdtime : %s\n",
|
|
|
|
option_holdtime ? "yes" : "no");
|
|
|
|
vty_out(vty,
|
|
|
|
" Hello Option - LAN Prune Delay : %s\n",
|
|
|
|
option_lan_prune_delay ? "yes" : "no");
|
|
|
|
vty_out(vty,
|
|
|
|
" Hello Option - T-bit : %s\n",
|
|
|
|
option_t_bit ? "yes" : "no");
|
|
|
|
bfd_sess_show(vty, json_ifp,
|
|
|
|
neigh->bfd_session);
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found_neighbor)
|
|
|
|
vty_out(vty, "%% No such interface or neighbor\n");
|
|
|
|
}
|
|
|
|
|
2022-03-02 10:22:13 +01:00
|
|
|
void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
|
|
|
|
json_object *json)
|
2022-02-08 18:14:26 +01:00
|
|
|
{
|
|
|
|
struct listnode *neighnode;
|
|
|
|
struct interface *ifp;
|
|
|
|
struct pim_interface *pim_ifp;
|
|
|
|
struct pim_neighbor *neigh;
|
|
|
|
time_t now;
|
|
|
|
char uptime[10];
|
|
|
|
char expire[10];
|
2022-03-02 10:22:13 +01:00
|
|
|
char neigh_src_str[PIM_ADDRSTRLEN];
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object *json_ifp_rows = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
now = pim_time_monotonic_sec();
|
|
|
|
|
2022-03-02 10:22:13 +01:00
|
|
|
if (!json) {
|
2022-02-08 18:14:26 +01:00
|
|
|
vty_out(vty,
|
|
|
|
"Interface Neighbor Uptime Holdtime DR Pri\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pim_ifp->pim_sock_fd < 0)
|
|
|
|
continue;
|
|
|
|
|
2022-03-02 10:22:13 +01:00
|
|
|
if (json)
|
2022-02-08 18:14:26 +01:00
|
|
|
json_ifp_rows = json_object_new_object();
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
|
|
|
|
neigh)) {
|
2022-03-02 10:22:13 +01:00
|
|
|
snprintfrr(neigh_src_str, sizeof(neigh_src_str),
|
|
|
|
"%pPAs", &neigh->source_addr);
|
2022-02-08 18:14:26 +01:00
|
|
|
pim_time_uptime(uptime, sizeof(uptime),
|
|
|
|
now - neigh->creation);
|
|
|
|
pim_time_timer_to_hhmmss(expire, sizeof(expire),
|
|
|
|
neigh->t_expire_timer);
|
|
|
|
|
2022-03-02 10:22:13 +01:00
|
|
|
if (json) {
|
2022-02-08 18:14:26 +01:00
|
|
|
json_row = json_object_new_object();
|
|
|
|
json_object_string_add(json_row, "interface",
|
|
|
|
ifp->name);
|
|
|
|
json_object_string_add(json_row, "neighbor",
|
|
|
|
neigh_src_str);
|
|
|
|
json_object_string_add(json_row, "upTime",
|
|
|
|
uptime);
|
|
|
|
json_object_string_add(json_row, "holdTime",
|
|
|
|
expire);
|
|
|
|
json_object_int_add(json_row, "holdTimeMax",
|
|
|
|
neigh->holdtime);
|
|
|
|
json_object_int_add(json_row, "drPriority",
|
|
|
|
neigh->dr_priority);
|
|
|
|
json_object_object_add(json_ifp_rows,
|
|
|
|
neigh_src_str, json_row);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
vty_out(vty, "%-16s %15s %8s %8s %6d\n",
|
|
|
|
ifp->name, neigh_src_str, uptime,
|
|
|
|
expire, neigh->dr_priority);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-02 10:22:13 +01:00
|
|
|
if (json) {
|
2022-02-08 18:14:26 +01:00
|
|
|
json_object_object_add(json, ifp->name, json_ifp_rows);
|
|
|
|
json_ifp_rows = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-18 16:16:51 +01:00
|
|
|
|
|
|
|
int gm_process_query_max_response_time_cmd(struct vty *vty,
|
|
|
|
const char *qmrt_str)
|
|
|
|
{
|
|
|
|
const struct lyd_node *pim_enable_dnode;
|
|
|
|
|
|
|
|
pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
|
|
|
|
FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
|
|
|
|
if (!pim_enable_dnode) {
|
|
|
|
nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
|
|
|
|
} else {
|
|
|
|
if (!yang_dnode_get_bool(pim_enable_dnode, "."))
|
|
|
|
nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
|
|
|
|
"true");
|
|
|
|
}
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
|
|
|
|
qmrt_str);
|
|
|
|
return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int gm_process_no_query_max_response_time_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_DESTROY,
|
|
|
|
NULL);
|
|
|
|
return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
2022-01-18 16:24:11 +01:00
|
|
|
|
|
|
|
int gm_process_last_member_query_count_cmd(struct vty *vty,
|
|
|
|
const char *lmqc_str)
|
|
|
|
{
|
|
|
|
const struct lyd_node *pim_enable_dnode;
|
|
|
|
|
|
|
|
pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
|
|
|
|
FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
if (!pim_enable_dnode) {
|
|
|
|
nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
|
|
|
|
} else {
|
|
|
|
if (!yang_dnode_get_bool(pim_enable_dnode, "."))
|
|
|
|
nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
|
|
|
|
"true");
|
|
|
|
}
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
|
|
|
|
lmqc_str);
|
|
|
|
return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int gm_process_no_last_member_query_count_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_DESTROY,
|
|
|
|
NULL);
|
|
|
|
return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
2022-01-18 16:31:56 +01:00
|
|
|
|
|
|
|
int gm_process_last_member_query_interval_cmd(struct vty *vty,
|
|
|
|
const char *lmqi_str)
|
|
|
|
{
|
|
|
|
const struct lyd_node *pim_enable_dnode;
|
|
|
|
|
|
|
|
pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
|
|
|
|
FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
if (!pim_enable_dnode) {
|
|
|
|
nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
|
|
|
|
} else {
|
|
|
|
if (!yang_dnode_get_bool(pim_enable_dnode, "."))
|
|
|
|
nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
|
|
|
|
"true");
|
|
|
|
}
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
|
|
|
|
lmqi_str);
|
|
|
|
return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int gm_process_no_last_member_query_interval_cmd(struct vty *vty)
|
|
|
|
{
|
|
|
|
nb_cli_enqueue_change(vty, "./last-member-query-interval",
|
|
|
|
NB_OP_DESTROY, NULL);
|
|
|
|
return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
}
|
2022-04-04 15:01:50 +02:00
|
|
|
|
|
|
|
int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation,
|
|
|
|
const char *src_str)
|
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
char ssmpingd_ip_xpath[XPATH_MAXLEN];
|
|
|
|
|
|
|
|
vrfname = pim_cli_get_vrf_name(vty);
|
|
|
|
if (vrfname == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
|
|
|
|
FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
|
|
|
|
FRR_PIM_AF_XPATH_VAL);
|
|
|
|
strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
|
|
|
|
sizeof(ssmpingd_ip_xpath));
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, operation, src_str);
|
|
|
|
|
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
|
|
|
}
|
2022-04-07 12:35:22 +02:00
|
|
|
|
|
|
|
static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
|
|
|
|
time_t now)
|
|
|
|
{
|
|
|
|
char uptime_scan_oil[10];
|
|
|
|
char uptime_mroute_add[10];
|
|
|
|
char uptime_mroute_del[10];
|
|
|
|
|
|
|
|
pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
|
|
|
|
pim->scan_oil_last);
|
|
|
|
pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
|
|
|
|
pim->mroute_add_last);
|
|
|
|
pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
|
|
|
|
pim->mroute_del_last);
|
|
|
|
|
|
|
|
vty_out(vty,
|
|
|
|
"Scan OIL - Last: %s Events: %lld\n"
|
|
|
|
"MFC Add - Last: %s Events: %lld\n"
|
|
|
|
"MFC Del - Last: %s Events: %lld\n",
|
|
|
|
uptime_scan_oil, (long long)pim->scan_oil_events,
|
|
|
|
uptime_mroute_add, (long long)pim->mroute_add_events,
|
|
|
|
uptime_mroute_del, (long long)pim->mroute_del_events);
|
|
|
|
}
|
|
|
|
|
|
|
|
void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
|
2022-04-14 09:07:41 +02:00
|
|
|
json_object *json)
|
2022-04-07 12:35:22 +02:00
|
|
|
{
|
|
|
|
struct interface *ifp;
|
2022-08-10 11:04:04 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-04-07 12:35:22 +02:00
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
2022-08-10 11:04:04 +02:00
|
|
|
if (!json) {
|
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(
|
|
|
|
tt,
|
|
|
|
"Interface|Address|ifi|Vif|PktsIn|PktsOut|BytesIn|BytesOut");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
|
|
|
}
|
2022-04-07 12:35:22 +02:00
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
struct pim_interface *pim_ifp;
|
2022-04-14 08:30:28 +02:00
|
|
|
#if PIM_IPV == 4
|
2022-04-07 12:35:22 +02:00
|
|
|
struct sioc_vif_req vreq;
|
2022-04-14 08:30:28 +02:00
|
|
|
#else
|
|
|
|
struct sioc_mif_req6 vreq;
|
|
|
|
#endif
|
2022-04-07 12:35:22 +02:00
|
|
|
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
memset(&vreq, 0, sizeof(vreq));
|
2022-04-14 08:30:28 +02:00
|
|
|
#if PIM_IPV == 4
|
2022-04-07 12:35:22 +02:00
|
|
|
vreq.vifi = pim_ifp->mroute_vif_index;
|
|
|
|
if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
|
|
|
|
zlog_warn(
|
|
|
|
"ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
|
|
|
|
(unsigned long)SIOCGETVIFCNT, ifp->name,
|
|
|
|
pim_ifp->mroute_vif_index, errno,
|
|
|
|
safe_strerror(errno));
|
|
|
|
}
|
2022-04-14 08:30:28 +02:00
|
|
|
#else
|
|
|
|
vreq.mifi = pim_ifp->mroute_vif_index;
|
|
|
|
if (ioctl(pim->mroute_socket, SIOCGETMIFCNT_IN6, &vreq)) {
|
|
|
|
zlog_warn(
|
|
|
|
"ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
|
|
|
|
(unsigned long)SIOCGETMIFCNT_IN6, ifp->name,
|
|
|
|
pim_ifp->mroute_vif_index, errno,
|
|
|
|
safe_strerror(errno));
|
|
|
|
}
|
|
|
|
#endif
|
2022-04-07 12:35:22 +02:00
|
|
|
|
2022-04-14 09:07:41 +02:00
|
|
|
if (json) {
|
2022-04-07 12:35:22 +02:00
|
|
|
json_row = json_object_new_object();
|
|
|
|
json_object_string_add(json_row, "name", ifp->name);
|
|
|
|
json_object_string_add(json_row, "state",
|
|
|
|
if_is_up(ifp) ? "up" : "down");
|
2022-04-14 08:30:28 +02:00
|
|
|
json_object_string_addf(json_row, "address", "%pPA",
|
2022-04-07 12:35:22 +02:00
|
|
|
&pim_ifp->primary_address);
|
|
|
|
json_object_int_add(json_row, "ifIndex", ifp->ifindex);
|
|
|
|
json_object_int_add(json_row, "vif",
|
|
|
|
pim_ifp->mroute_vif_index);
|
|
|
|
json_object_int_add(json_row, "pktsIn",
|
|
|
|
(unsigned long)vreq.icount);
|
|
|
|
json_object_int_add(json_row, "pktsOut",
|
|
|
|
(unsigned long)vreq.ocount);
|
|
|
|
json_object_int_add(json_row, "bytesIn",
|
|
|
|
(unsigned long)vreq.ibytes);
|
|
|
|
json_object_int_add(json_row, "bytesOut",
|
|
|
|
(unsigned long)vreq.obytes);
|
|
|
|
json_object_object_add(json, ifp->name, json_row);
|
|
|
|
} else {
|
2022-08-10 11:04:04 +02:00
|
|
|
ttable_add_row(tt, "%s|%pPAs|%d|%d|%lu|%lu|%lu|%lu",
|
|
|
|
ifp->name, &pim_ifp->primary_address,
|
|
|
|
ifp->ifindex, pim_ifp->mroute_vif_index,
|
|
|
|
(unsigned long)vreq.icount,
|
|
|
|
(unsigned long)vreq.ocount,
|
|
|
|
(unsigned long)vreq.ibytes,
|
|
|
|
(unsigned long)vreq.obytes);
|
2022-04-07 12:35:22 +02:00
|
|
|
}
|
|
|
|
}
|
2022-08-10 11:04:04 +02:00
|
|
|
/* Dump the generated table. */
|
|
|
|
if (!json) {
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
|
|
|
}
|
2022-04-07 12:35:22 +02:00
|
|
|
}
|
|
|
|
|
2022-04-14 08:30:28 +02:00
|
|
|
void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
|
2022-04-07 12:35:22 +02:00
|
|
|
{
|
|
|
|
struct vrf *vrf = pim->vrf;
|
|
|
|
time_t now = pim_time_monotonic_sec();
|
|
|
|
char uptime[10];
|
|
|
|
char mlag_role[80];
|
|
|
|
|
|
|
|
pim = vrf->info;
|
|
|
|
|
|
|
|
vty_out(vty, "Router MLAG Role: %s\n",
|
|
|
|
mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
|
|
|
|
vty_out(vty, "Mroute socket descriptor:");
|
|
|
|
|
|
|
|
vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
|
2022-08-02 08:12:53 +02:00
|
|
|
vty_out(vty, "PIM Register socket descriptor:");
|
|
|
|
vty_out(vty, " %d(%s)\n", pim->reg_sock, vrf->name);
|
2022-04-07 12:35:22 +02:00
|
|
|
|
|
|
|
pim_time_uptime(uptime, sizeof(uptime),
|
|
|
|
now - pim->mroute_socket_creation);
|
|
|
|
vty_out(vty, "Mroute socket uptime: %s\n", uptime);
|
|
|
|
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
pim_zebra_zclient_update(vty);
|
|
|
|
pim_zlookup_show_ip_multicast(vty);
|
|
|
|
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
|
|
|
|
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
|
|
|
|
vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
|
|
|
|
vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
|
|
|
|
vty_out(vty, "PIM ECMP Rebalance: %s\n",
|
|
|
|
pim->ecmp_rebalance_enable ? "Enable" : "Disable");
|
|
|
|
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
pim_show_rpf_refresh_stats(vty, pim, now, NULL);
|
|
|
|
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
show_scan_oil_stats(pim, vty, now);
|
|
|
|
|
2022-04-14 09:07:41 +02:00
|
|
|
show_multicast_interfaces(pim, vty, NULL);
|
2022-04-07 12:35:22 +02:00
|
|
|
}
|
2022-04-08 08:52:28 +02:00
|
|
|
|
|
|
|
void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
|
|
|
|
bool fill, json_object *json)
|
2022-04-08 07:42:03 +02:00
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct channel_oil *c_oil;
|
|
|
|
struct static_route *s_route;
|
2022-08-10 17:58:23 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-04-08 07:42:03 +02:00
|
|
|
time_t now;
|
|
|
|
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;
|
2022-04-08 08:52:28 +02:00
|
|
|
char grp_str[PIM_ADDRSTRLEN];
|
|
|
|
char src_str[PIM_ADDRSTRLEN];
|
2022-04-08 07:42:03 +02:00
|
|
|
char in_ifname[INTERFACE_NAMSIZ + 1];
|
|
|
|
char out_ifname[INTERFACE_NAMSIZ + 1];
|
|
|
|
int oif_vif_index;
|
|
|
|
struct interface *ifp_in;
|
|
|
|
char proto[100];
|
|
|
|
char state_str[PIM_REG_STATE_STR_LEN];
|
|
|
|
char mroute_uptime[10];
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (!json) {
|
2022-04-08 07:42:03 +02:00
|
|
|
vty_out(vty, "IP Multicast Routing Table\n");
|
|
|
|
vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
|
|
|
|
vty_out(vty,
|
|
|
|
" R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
|
2022-08-10 17:58:23 +02:00
|
|
|
|
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(
|
|
|
|
tt, "Source|Group|Flags|Proto|Input|Output|TTL|Uptime");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
now = pim_time_monotonic_sec();
|
|
|
|
|
|
|
|
/* print list of PIM and IGMP routes */
|
|
|
|
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
|
|
|
found_oif = 0;
|
|
|
|
first = 1;
|
|
|
|
if (!c_oil->installed)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!pim_addr_is_any(sg->grp) &&
|
2022-04-08 08:52:28 +02:00
|
|
|
pim_addr_cmp(sg->grp, *oil_mcastgrp(c_oil)))
|
2022-04-08 07:42:03 +02:00
|
|
|
continue;
|
|
|
|
if (!pim_addr_is_any(sg->src) &&
|
2022-04-08 08:52:28 +02:00
|
|
|
pim_addr_cmp(sg->src, *oil_origin(c_oil)))
|
2022-04-08 07:42:03 +02:00
|
|
|
continue;
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
|
|
|
|
oil_mcastgrp(c_oil));
|
|
|
|
snprintfrr(src_str, sizeof(src_str), "%pPAs",
|
|
|
|
oil_origin(c_oil));
|
2022-04-08 07:42:03 +02:00
|
|
|
|
|
|
|
strlcpy(state_str, "S", sizeof(state_str));
|
|
|
|
/* When a non DR receives a igmp join, it creates a (*,G)
|
2022-04-08 08:52:28 +02:00
|
|
|
* channel_oil without any upstream creation
|
|
|
|
*/
|
2022-04-08 07:42:03 +02:00
|
|
|
if (c_oil->up) {
|
|
|
|
if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
|
|
|
|
strlcat(state_str, "C", sizeof(state_str));
|
|
|
|
if (pim_upstream_is_sg_rpt(c_oil->up))
|
|
|
|
strlcat(state_str, "R", sizeof(state_str));
|
|
|
|
if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
|
|
|
|
strlcat(state_str, "F", sizeof(state_str));
|
|
|
|
if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
|
|
|
|
strlcat(state_str, "T", sizeof(state_str));
|
|
|
|
}
|
|
|
|
if (pim_channel_oil_empty(c_oil))
|
|
|
|
strlcat(state_str, "P", sizeof(state_str));
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
|
2022-04-08 07:42:03 +02:00
|
|
|
|
|
|
|
if (ifp_in)
|
|
|
|
strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
|
|
|
|
else
|
|
|
|
strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
|
|
|
|
|
|
|
|
|
|
|
|
pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
|
|
|
|
now - c_oil->mroute_creation);
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (json) {
|
2022-04-08 07:42:03 +02:00
|
|
|
|
|
|
|
/* 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,
|
2022-04-08 08:52:28 +02:00
|
|
|
* 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);
|
2022-04-08 07:42:03 +02:00
|
|
|
json_object_int_add(json_source, "installed",
|
|
|
|
c_oil->installed);
|
|
|
|
json_object_int_add(json_source, "refCount",
|
|
|
|
c_oil->oil_ref_count);
|
|
|
|
json_object_int_add(json_source, "oilSize",
|
|
|
|
c_oil->oil_size);
|
|
|
|
json_object_int_add(json_source, "OilInheritedRescan",
|
|
|
|
c_oil->oil_inherited_rescan);
|
|
|
|
json_object_int_add(json_source, "oilInheritedRescan",
|
|
|
|
c_oil->oil_inherited_rescan);
|
|
|
|
json_object_string_add(json_source, "iif", in_ifname);
|
|
|
|
json_object_string_add(json_source, "upTime",
|
|
|
|
mroute_uptime);
|
|
|
|
json_oil = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
|
|
|
|
++oif_vif_index) {
|
|
|
|
struct interface *ifp_out;
|
|
|
|
int ttl;
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
ttl = oil_if_has(c_oil, oif_vif_index);
|
2022-04-08 07:42:03 +02:00
|
|
|
if (ttl < 1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* do not display muted OIFs */
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_MUTE)
|
2022-04-08 07:42:03 +02:00
|
|
|
continue;
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (*oil_parent(c_oil) == oif_vif_index &&
|
|
|
|
!pim_mroute_allow_iif_in_oil(c_oil, oif_vif_index))
|
2022-04-08 07:42:03 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
|
|
|
|
found_oif = 1;
|
|
|
|
|
|
|
|
if (ifp_out)
|
2022-04-08 08:52:28 +02:00
|
|
|
strlcpy(out_ifname, ifp_out->name,
|
|
|
|
sizeof(out_ifname));
|
2022-04-08 07:42:03 +02:00
|
|
|
else
|
2022-04-08 08:52:28 +02:00
|
|
|
strlcpy(out_ifname, "<oif?>",
|
|
|
|
sizeof(out_ifname));
|
2022-04-08 07:42:03 +02:00
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (json) {
|
2022-04-08 07:42:03 +02:00
|
|
|
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);
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] &
|
|
|
|
PIM_OIF_FLAG_PROTO_PIM)
|
2022-04-08 07:42:03 +02:00
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_ifp_out, "protocolPim");
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] &
|
|
|
|
PIM_OIF_FLAG_PROTO_GM)
|
|
|
|
#if PIM_IPV == 4
|
2022-04-08 07:42:03 +02:00
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_ifp_out, "protocolIgmp");
|
2022-04-08 08:52:28 +02:00
|
|
|
#else
|
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_ifp_out, "protocolMld");
|
|
|
|
#endif
|
2022-04-08 07:42:03 +02:00
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] &
|
|
|
|
PIM_OIF_FLAG_PROTO_VXLAN)
|
2022-04-08 07:42:03 +02:00
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_ifp_out, "protocolVxlan");
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] &
|
|
|
|
PIM_OIF_FLAG_PROTO_STAR)
|
2022-04-08 07:42:03 +02:00
|
|
|
json_object_boolean_true_add(
|
|
|
|
json_ifp_out,
|
|
|
|
"protocolInherited");
|
|
|
|
|
|
|
|
json_object_string_add(json_ifp_out,
|
|
|
|
"inboundInterface",
|
|
|
|
in_ifname);
|
|
|
|
json_object_int_add(json_ifp_out, "iVifI",
|
2022-04-08 08:52:28 +02:00
|
|
|
*oil_parent(c_oil));
|
2022-04-08 07:42:03 +02:00
|
|
|
json_object_string_add(json_ifp_out,
|
|
|
|
"outboundInterface",
|
|
|
|
out_ifname);
|
|
|
|
json_object_int_add(json_ifp_out, "oVifI",
|
|
|
|
oif_vif_index);
|
|
|
|
json_object_int_add(json_ifp_out, "ttl", ttl);
|
|
|
|
json_object_string_add(json_ifp_out, "upTime",
|
|
|
|
mroute_uptime);
|
|
|
|
json_object_string_add(json_source, "flags",
|
|
|
|
state_str);
|
|
|
|
if (!json_oil) {
|
|
|
|
json_oil = json_object_new_object();
|
|
|
|
json_object_object_add(json_source,
|
|
|
|
"oil", json_oil);
|
|
|
|
}
|
|
|
|
json_object_object_add(json_oil, out_ifname,
|
|
|
|
json_ifp_out);
|
|
|
|
} else {
|
|
|
|
proto[0] = '\0';
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] &
|
|
|
|
PIM_OIF_FLAG_PROTO_PIM) {
|
2022-04-08 07:42:03 +02:00
|
|
|
strlcpy(proto, "PIM", sizeof(proto));
|
|
|
|
}
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] &
|
|
|
|
PIM_OIF_FLAG_PROTO_GM) {
|
|
|
|
#if PIM_IPV == 4
|
2022-04-08 07:42:03 +02:00
|
|
|
strlcpy(proto, "IGMP", sizeof(proto));
|
2022-04-08 08:52:28 +02:00
|
|
|
#else
|
|
|
|
strlcpy(proto, "MLD", sizeof(proto));
|
|
|
|
#endif
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] &
|
|
|
|
PIM_OIF_FLAG_PROTO_VXLAN) {
|
2022-04-08 07:42:03 +02:00
|
|
|
strlcpy(proto, "VxLAN", sizeof(proto));
|
|
|
|
}
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (c_oil->oif_flags[oif_vif_index] &
|
|
|
|
PIM_OIF_FLAG_PROTO_STAR) {
|
2022-04-08 07:42:03 +02:00
|
|
|
strlcpy(proto, "STAR", sizeof(proto));
|
|
|
|
}
|
|
|
|
|
2022-08-10 17:58:23 +02:00
|
|
|
ttable_add_row(tt, "%s|%s|%s|%s|%s|%s|%d|%s",
|
|
|
|
src_str, grp_str, state_str,
|
|
|
|
proto, in_ifname, out_ifname,
|
|
|
|
ttl, mroute_uptime);
|
2022-04-08 07:42:03 +02:00
|
|
|
|
|
|
|
if (first) {
|
|
|
|
src_str[0] = '\0';
|
|
|
|
grp_str[0] = '\0';
|
|
|
|
in_ifname[0] = '\0';
|
|
|
|
state_str[0] = '\0';
|
|
|
|
mroute_uptime[0] = '\0';
|
|
|
|
first = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (!json && !found_oif) {
|
2022-08-10 17:58:23 +02:00
|
|
|
ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
|
|
|
|
oil_origin(c_oil), oil_mcastgrp(c_oil),
|
|
|
|
state_str, "none", in_ifname, "none", 0,
|
|
|
|
"--:--:--");
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Print list of static routes */
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
|
|
|
|
first = 1;
|
|
|
|
|
|
|
|
if (!s_route->c_oil.installed)
|
|
|
|
continue;
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &s_route->group);
|
|
|
|
snprintfrr(src_str, sizeof(src_str), "%pPAs", &s_route->source);
|
2022-04-08 07:42:03 +02:00
|
|
|
ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
|
|
|
|
found_oif = 0;
|
|
|
|
|
|
|
|
if (ifp_in)
|
|
|
|
strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
|
|
|
|
else
|
|
|
|
strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (json) {
|
2022-04-08 07:42:03 +02:00
|
|
|
|
|
|
|
/* 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
|
2022-04-08 08:52:28 +02:00
|
|
|
* it doesn't exist
|
|
|
|
*/
|
2022-04-08 07:42:03 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_object_string_add(json_source, "iif", in_ifname);
|
|
|
|
json_oil = NULL;
|
|
|
|
} else {
|
|
|
|
strlcpy(proto, "STATIC", sizeof(proto));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
|
|
|
|
++oif_vif_index) {
|
|
|
|
struct interface *ifp_out;
|
|
|
|
char oif_uptime[10];
|
|
|
|
int ttl;
|
|
|
|
|
|
|
|
ttl = s_route->oif_ttls[oif_vif_index];
|
|
|
|
if (ttl < 1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
|
|
|
|
pim_time_uptime(
|
|
|
|
oif_uptime, sizeof(oif_uptime),
|
2022-04-08 08:52:28 +02:00
|
|
|
now - s_route->c_oil
|
|
|
|
.oif_creation[oif_vif_index]);
|
2022-04-08 07:42:03 +02:00
|
|
|
found_oif = 1;
|
|
|
|
|
|
|
|
if (ifp_out)
|
2022-04-08 08:52:28 +02:00
|
|
|
strlcpy(out_ifname, ifp_out->name,
|
|
|
|
sizeof(out_ifname));
|
2022-04-08 07:42:03 +02:00
|
|
|
else
|
2022-04-08 08:52:28 +02:00
|
|
|
strlcpy(out_ifname, "<oif?>",
|
|
|
|
sizeof(out_ifname));
|
2022-04-08 07:42:03 +02:00
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (json) {
|
2022-04-08 07:42:03 +02:00
|
|
|
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_boolean_true_add(json_ifp_out,
|
|
|
|
"protocolStatic");
|
|
|
|
json_object_string_add(json_ifp_out,
|
|
|
|
"inboundInterface",
|
|
|
|
in_ifname);
|
|
|
|
json_object_int_add(
|
|
|
|
json_ifp_out, "iVifI",
|
2022-04-08 08:52:28 +02:00
|
|
|
*oil_parent(&s_route->c_oil));
|
2022-04-08 07:42:03 +02:00
|
|
|
json_object_string_add(json_ifp_out,
|
|
|
|
"outboundInterface",
|
|
|
|
out_ifname);
|
|
|
|
json_object_int_add(json_ifp_out, "oVifI",
|
|
|
|
oif_vif_index);
|
|
|
|
json_object_int_add(json_ifp_out, "ttl", ttl);
|
|
|
|
json_object_string_add(json_ifp_out, "upTime",
|
|
|
|
oif_uptime);
|
|
|
|
if (!json_oil) {
|
|
|
|
json_oil = json_object_new_object();
|
|
|
|
json_object_object_add(json_source,
|
|
|
|
"oil", json_oil);
|
|
|
|
}
|
|
|
|
json_object_object_add(json_oil, out_ifname,
|
|
|
|
json_ifp_out);
|
|
|
|
} else {
|
2022-08-10 17:58:23 +02:00
|
|
|
ttable_add_row(
|
|
|
|
tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
|
2022-04-08 08:52:28 +02:00
|
|
|
&s_route->source, &s_route->group, "-",
|
|
|
|
proto, in_ifname, out_ifname, ttl,
|
|
|
|
oif_uptime);
|
2022-04-08 07:42:03 +02:00
|
|
|
if (first && !fill) {
|
|
|
|
src_str[0] = '\0';
|
|
|
|
grp_str[0] = '\0';
|
|
|
|
in_ifname[0] = '\0';
|
|
|
|
first = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-08 08:52:28 +02:00
|
|
|
if (!json && !found_oif) {
|
2022-08-10 17:58:23 +02:00
|
|
|
ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
|
|
|
|
&s_route->source, &s_route->group, "-",
|
|
|
|
proto, in_ifname, "none", 0, "--:--:--");
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
}
|
2022-08-10 17:58:23 +02:00
|
|
|
/* Dump the generated table. */
|
|
|
|
if (!json) {
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
|
|
|
}
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
|
|
|
|
json_object *json,
|
2022-08-11 10:01:51 +02:00
|
|
|
struct ttable *tt)
|
2022-04-08 07:42:03 +02:00
|
|
|
{
|
|
|
|
json_object *json_group = NULL;
|
|
|
|
json_object *json_source = NULL;
|
|
|
|
|
|
|
|
if (!c_oil->installed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pim_mroute_update_counters(c_oil);
|
|
|
|
|
|
|
|
if (json) {
|
2022-04-08 09:20:53 +02:00
|
|
|
char group_str[PIM_ADDRSTRLEN];
|
|
|
|
char source_str[PIM_ADDRSTRLEN];
|
|
|
|
|
|
|
|
snprintfrr(group_str, sizeof(group_str), "%pPAs",
|
|
|
|
oil_mcastgrp(c_oil));
|
|
|
|
snprintfrr(source_str, sizeof(source_str), "%pPAs",
|
|
|
|
oil_origin(c_oil));
|
|
|
|
|
2022-04-08 07:42:03 +02:00
|
|
|
json_object_object_get_ex(json, group_str, &json_group);
|
|
|
|
|
|
|
|
if (!json_group) {
|
|
|
|
json_group = json_object_new_object();
|
|
|
|
json_object_object_add(json, group_str, json_group);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_source = json_object_new_object();
|
|
|
|
json_object_object_add(json_group, source_str, json_source);
|
|
|
|
json_object_int_add(json_source, "lastUsed",
|
|
|
|
c_oil->cc.lastused / 100);
|
|
|
|
json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
|
|
|
|
json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
|
|
|
|
json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
|
|
|
|
|
|
|
|
} else {
|
2022-08-11 10:01:51 +02:00
|
|
|
ttable_add_row(tt, "%pPAs|%pPAs|%llu|%ld|%ld|%ld",
|
|
|
|
oil_origin(c_oil), oil_mcastgrp(c_oil),
|
|
|
|
c_oil->cc.lastused / 100,
|
|
|
|
c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
|
|
|
|
c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
|
|
|
|
c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void show_mroute_count(struct pim_instance *pim, struct vty *vty,
|
2022-04-08 09:20:53 +02:00
|
|
|
json_object *json)
|
2022-04-08 07:42:03 +02:00
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct channel_oil *c_oil;
|
|
|
|
struct static_route *sr;
|
2022-08-11 10:01:51 +02:00
|
|
|
struct ttable *tt = NULL;
|
|
|
|
char *table = NULL;
|
2022-04-08 07:42:03 +02:00
|
|
|
|
2022-04-08 09:20:53 +02:00
|
|
|
if (!json) {
|
2022-04-08 07:42:03 +02:00
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
2022-08-11 10:01:51 +02:00
|
|
|
/* Prepare table. */
|
|
|
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(tt,
|
|
|
|
"Source|Group|LastUsed|Packets|Bytes|WrongIf");
|
|
|
|
tt->style.cell.rpad = 2;
|
|
|
|
tt->style.corner = '+';
|
|
|
|
ttable_restyle(tt);
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Print PIM and IGMP route counts */
|
|
|
|
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
|
2022-08-18 08:09:11 +02:00
|
|
|
show_mroute_count_per_channel_oil(c_oil, json, tt);
|
2022-04-08 07:42:03 +02:00
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
|
2022-08-18 08:09:11 +02:00
|
|
|
show_mroute_count_per_channel_oil(&sr->c_oil, json, tt);
|
2022-08-11 10:01:51 +02:00
|
|
|
|
|
|
|
/* Dump the generated table. */
|
|
|
|
if (!json) {
|
|
|
|
table = ttable_dump(tt, "\n");
|
|
|
|
vty_out(vty, "%s\n", table);
|
|
|
|
XFREE(MTYPE_TMP, table);
|
|
|
|
ttable_del(tt);
|
|
|
|
}
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
|
2022-04-08 09:34:02 +02:00
|
|
|
json_object *json)
|
2022-04-08 07:42:03 +02:00
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct channel_oil *c_oil;
|
|
|
|
struct static_route *s_route;
|
|
|
|
uint32_t starg_sw_mroute_cnt = 0;
|
|
|
|
uint32_t sg_sw_mroute_cnt = 0;
|
|
|
|
uint32_t starg_hw_mroute_cnt = 0;
|
|
|
|
uint32_t sg_hw_mroute_cnt = 0;
|
|
|
|
json_object *json_starg = NULL;
|
|
|
|
json_object *json_sg = NULL;
|
|
|
|
|
|
|
|
if (!json)
|
|
|
|
vty_out(vty, "Mroute Type Installed/Total\n");
|
|
|
|
|
|
|
|
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
|
|
|
if (!c_oil->installed) {
|
2022-04-08 09:34:02 +02:00
|
|
|
if (pim_addr_is_any(*oil_origin(c_oil)))
|
2022-04-08 07:42:03 +02:00
|
|
|
starg_sw_mroute_cnt++;
|
|
|
|
else
|
|
|
|
sg_sw_mroute_cnt++;
|
|
|
|
} else {
|
2022-04-08 09:34:02 +02:00
|
|
|
if (pim_addr_is_any(*oil_origin(c_oil)))
|
2022-04-08 07:42:03 +02:00
|
|
|
starg_hw_mroute_cnt++;
|
|
|
|
else
|
|
|
|
sg_hw_mroute_cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
|
|
|
|
if (!s_route->c_oil.installed) {
|
2022-04-08 09:34:02 +02:00
|
|
|
if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
|
2022-04-08 07:42:03 +02:00
|
|
|
starg_sw_mroute_cnt++;
|
|
|
|
else
|
|
|
|
sg_sw_mroute_cnt++;
|
|
|
|
} else {
|
2022-04-08 09:34:02 +02:00
|
|
|
if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
|
2022-04-08 07:42:03 +02:00
|
|
|
starg_hw_mroute_cnt++;
|
|
|
|
else
|
|
|
|
sg_hw_mroute_cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!json) {
|
|
|
|
vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
|
|
|
|
starg_sw_mroute_cnt + starg_hw_mroute_cnt);
|
|
|
|
vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
|
|
|
|
sg_sw_mroute_cnt + sg_hw_mroute_cnt);
|
|
|
|
vty_out(vty, "------\n");
|
|
|
|
vty_out(vty, "%-20s %u/%u\n", "Total",
|
|
|
|
(starg_hw_mroute_cnt + sg_hw_mroute_cnt),
|
2022-04-08 09:34:02 +02:00
|
|
|
(starg_sw_mroute_cnt + starg_hw_mroute_cnt +
|
|
|
|
sg_sw_mroute_cnt + sg_hw_mroute_cnt));
|
2022-04-08 07:42:03 +02:00
|
|
|
} else {
|
|
|
|
/* (*,G) route details */
|
|
|
|
json_starg = json_object_new_object();
|
|
|
|
json_object_object_add(json, "wildcardGroup", json_starg);
|
|
|
|
|
|
|
|
json_object_int_add(json_starg, "installed",
|
|
|
|
starg_hw_mroute_cnt);
|
|
|
|
json_object_int_add(json_starg, "total",
|
|
|
|
starg_sw_mroute_cnt + starg_hw_mroute_cnt);
|
|
|
|
|
|
|
|
/* (S, G) route details */
|
|
|
|
json_sg = json_object_new_object();
|
|
|
|
json_object_object_add(json, "sourceGroup", json_sg);
|
|
|
|
|
|
|
|
json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
|
|
|
|
json_object_int_add(json_sg, "total",
|
|
|
|
sg_sw_mroute_cnt + sg_hw_mroute_cnt);
|
|
|
|
|
|
|
|
json_object_int_add(json, "totalNumOfInstalledMroutes",
|
|
|
|
starg_hw_mroute_cnt + sg_hw_mroute_cnt);
|
|
|
|
json_object_int_add(json, "totalNumOfMroutes",
|
2022-04-08 09:34:02 +02:00
|
|
|
starg_sw_mroute_cnt + starg_hw_mroute_cnt +
|
|
|
|
sg_sw_mroute_cnt +
|
|
|
|
sg_hw_mroute_cnt);
|
2022-04-08 07:42:03 +02:00
|
|
|
}
|
|
|
|
}
|
2022-04-12 13:36:35 +02:00
|
|
|
|
2022-04-13 17:31:45 +02:00
|
|
|
int clear_ip_mroute_count_command(struct vty *vty, const char *name)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct channel_oil *c_oil;
|
|
|
|
struct static_route *sr;
|
|
|
|
struct vrf *v = pim_cmd_lookup(vty, name);
|
|
|
|
struct pim_instance *pim;
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
|
|
|
pim = v->info;
|
|
|
|
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
|
|
|
if (!c_oil->installed)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pim_mroute_update_counters(c_oil);
|
|
|
|
c_oil->cc.origpktcnt = c_oil->cc.pktcnt;
|
|
|
|
c_oil->cc.origbytecnt = c_oil->cc.bytecnt;
|
|
|
|
c_oil->cc.origwrong_if = c_oil->cc.wrong_if;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
|
|
|
|
if (!sr->c_oil.installed)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pim_mroute_update_counters(&sr->c_oil);
|
|
|
|
|
|
|
|
sr->c_oil.cc.origpktcnt = sr->c_oil.cc.pktcnt;
|
|
|
|
sr->c_oil.cc.origbytecnt = sr->c_oil.cc.bytecnt;
|
|
|
|
sr->c_oil.cc.origwrong_if = sr->c_oil.cc.wrong_if;
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-04-27 17:07:53 +02:00
|
|
|
struct vrf *pim_cmd_lookup(struct vty *vty, const char *name)
|
|
|
|
{
|
|
|
|
struct vrf *vrf;
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
vrf = vrf_lookup_by_name(name);
|
|
|
|
else
|
|
|
|
vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
|
|
|
|
|
|
|
if (!vrf)
|
|
|
|
vty_out(vty, "Specified VRF: %s does not exist\n", name);
|
|
|
|
|
|
|
|
return vrf;
|
|
|
|
}
|
|
|
|
|
2022-04-12 13:36:35 +02:00
|
|
|
void clear_mroute(struct pim_instance *pim)
|
|
|
|
{
|
|
|
|
struct pim_upstream *up;
|
|
|
|
struct interface *ifp;
|
|
|
|
|
|
|
|
/* scan interfaces */
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
struct pim_interface *pim_ifp = ifp->info;
|
|
|
|
struct pim_ifchannel *ch;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* deleting all ifchannels */
|
|
|
|
while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
|
|
|
|
ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
|
|
|
|
|
|
|
|
pim_ifchannel_delete(ch);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if PIM_IPV == 4
|
|
|
|
/* clean up all igmp groups */
|
|
|
|
struct gm_group *grp;
|
|
|
|
|
|
|
|
if (pim_ifp->gm_group_list) {
|
|
|
|
while (pim_ifp->gm_group_list->count) {
|
|
|
|
grp = listnode_head(pim_ifp->gm_group_list);
|
|
|
|
igmp_group_delete(grp);
|
|
|
|
}
|
|
|
|
}
|
2022-07-07 17:03:45 +02:00
|
|
|
#else
|
|
|
|
struct gm_if *gm_ifp;
|
|
|
|
|
|
|
|
gm_ifp = pim_ifp->mld;
|
|
|
|
if (gm_ifp)
|
|
|
|
gm_group_delete(gm_ifp);
|
2022-04-12 13:36:35 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clean up all upstreams*/
|
|
|
|
while ((up = rb_pim_upstream_first(&pim->upstream_head)))
|
|
|
|
pim_upstream_del(pim, up, __func__);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear_pim_statistics(struct pim_instance *pim)
|
|
|
|
{
|
|
|
|
struct interface *ifp;
|
|
|
|
|
|
|
|
pim->bsm_rcvd = 0;
|
|
|
|
pim->bsm_sent = 0;
|
|
|
|
pim->bsm_dropped = 0;
|
|
|
|
|
|
|
|
/* scan interfaces */
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
struct pim_interface *pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pim_ifp->pim_ifstat_bsm_cfg_miss = 0;
|
|
|
|
pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0;
|
|
|
|
pim_ifp->pim_ifstat_bsm_invalid_sz = 0;
|
|
|
|
}
|
|
|
|
}
|
2022-03-24 09:41:15 +01:00
|
|
|
|
2022-07-18 15:08:19 +02:00
|
|
|
int clear_pim_interface_traffic(const char *vrf, struct vty *vty)
|
|
|
|
{
|
|
|
|
struct interface *ifp = NULL;
|
|
|
|
struct pim_interface *pim_ifp = NULL;
|
|
|
|
|
|
|
|
struct vrf *v = pim_cmd_lookup(vty, vrf);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (v, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pim_ifp->pim_ifstat_hello_recv = 0;
|
|
|
|
pim_ifp->pim_ifstat_hello_sent = 0;
|
|
|
|
pim_ifp->pim_ifstat_join_recv = 0;
|
|
|
|
pim_ifp->pim_ifstat_join_send = 0;
|
|
|
|
pim_ifp->pim_ifstat_prune_recv = 0;
|
|
|
|
pim_ifp->pim_ifstat_prune_send = 0;
|
|
|
|
pim_ifp->pim_ifstat_reg_recv = 0;
|
|
|
|
pim_ifp->pim_ifstat_reg_send = 0;
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_recv = 0;
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_send = 0;
|
|
|
|
pim_ifp->pim_ifstat_assert_recv = 0;
|
|
|
|
pim_ifp->pim_ifstat_assert_send = 0;
|
|
|
|
pim_ifp->pim_ifstat_bsm_rx = 0;
|
|
|
|
pim_ifp->pim_ifstat_bsm_tx = 0;
|
|
|
|
#if PIM_IPV == 4
|
|
|
|
pim_ifp->igmp_ifstat_joins_sent = 0;
|
|
|
|
pim_ifp->igmp_ifstat_joins_failed = 0;
|
|
|
|
pim_ifp->igmp_peak_group_count = 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-03-24 09:41:15 +01:00
|
|
|
int pim_debug_pim_cmd(void)
|
|
|
|
{
|
|
|
|
PIM_DO_DEBUG_PIM_EVENTS;
|
|
|
|
PIM_DO_DEBUG_PIM_PACKETS;
|
|
|
|
PIM_DO_DEBUG_PIM_TRACE;
|
|
|
|
PIM_DO_DEBUG_MSDP_EVENTS;
|
|
|
|
PIM_DO_DEBUG_MSDP_PACKETS;
|
|
|
|
PIM_DO_DEBUG_BSM;
|
|
|
|
PIM_DO_DEBUG_VXLAN;
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_no_debug_pim_cmd(void)
|
|
|
|
{
|
|
|
|
PIM_DONT_DEBUG_PIM_EVENTS;
|
|
|
|
PIM_DONT_DEBUG_PIM_PACKETS;
|
|
|
|
PIM_DONT_DEBUG_PIM_TRACE;
|
|
|
|
PIM_DONT_DEBUG_MSDP_EVENTS;
|
|
|
|
PIM_DONT_DEBUG_MSDP_PACKETS;
|
|
|
|
|
|
|
|
PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
|
|
|
|
PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
|
2022-08-02 15:34:30 +02:00
|
|
|
PIM_DONT_DEBUG_BSM;
|
|
|
|
PIM_DONT_DEBUG_VXLAN;
|
2022-03-24 09:41:15 +01:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
2022-03-28 07:15:36 +02:00
|
|
|
|
|
|
|
int pim_debug_pim_packets_cmd(const char *hello, const char *joins,
|
|
|
|
const char *registers, struct vty *vty)
|
|
|
|
{
|
|
|
|
if (hello) {
|
|
|
|
PIM_DO_DEBUG_PIM_HELLO;
|
|
|
|
vty_out(vty, "PIM Hello debugging is on\n");
|
|
|
|
} else if (joins) {
|
|
|
|
PIM_DO_DEBUG_PIM_J_P;
|
|
|
|
vty_out(vty, "PIM Join/Prune debugging is on\n");
|
|
|
|
} else if (registers) {
|
|
|
|
PIM_DO_DEBUG_PIM_REG;
|
|
|
|
vty_out(vty, "PIM Register debugging is on\n");
|
|
|
|
} else {
|
|
|
|
PIM_DO_DEBUG_PIM_PACKETS;
|
|
|
|
vty_out(vty, "PIM Packet debugging is on\n");
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_no_debug_pim_packets_cmd(const char *hello, const char *joins,
|
|
|
|
const char *registers, struct vty *vty)
|
|
|
|
{
|
|
|
|
if (hello) {
|
|
|
|
PIM_DONT_DEBUG_PIM_HELLO;
|
|
|
|
vty_out(vty, "PIM Hello debugging is off\n");
|
|
|
|
} else if (joins) {
|
|
|
|
PIM_DONT_DEBUG_PIM_J_P;
|
|
|
|
vty_out(vty, "PIM Join/Prune debugging is off\n");
|
|
|
|
} else if (registers) {
|
|
|
|
PIM_DONT_DEBUG_PIM_REG;
|
|
|
|
vty_out(vty, "PIM Register debugging is off\n");
|
|
|
|
} else {
|
|
|
|
PIM_DONT_DEBUG_PIM_PACKETS;
|
|
|
|
vty_out(vty, "PIM Packet debugging is off\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
2022-06-09 07:49:16 +02:00
|
|
|
|
|
|
|
int pim_show_rpf_helper(const char *vrf, struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 07:49:16 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_rpf_vrf_all_helper(struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2022-06-09 09:49:38 +02:00
|
|
|
|
|
|
|
int pim_show_rp_helper(const char *vrf, struct vty *vty, const char *group_str,
|
|
|
|
const struct prefix *group, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 09:49:38 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_rp_vrf_all_helper(struct vty *vty, const char *group_str,
|
|
|
|
const struct prefix *group, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2022-06-09 10:33:01 +02:00
|
|
|
|
|
|
|
int pim_show_secondary_helper(const char *vrf, struct vty *vty)
|
|
|
|
{
|
|
|
|
struct pim_instance *pim;
|
|
|
|
struct vrf *v;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 10:33:01 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
pim_show_neighbors_secondary(pim, vty);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
2022-06-09 10:59:58 +02:00
|
|
|
|
|
|
|
int pim_show_statistics_helper(const char *vrf, struct vty *vty,
|
|
|
|
const char *word, bool uj)
|
|
|
|
{
|
|
|
|
struct pim_instance *pim;
|
|
|
|
struct vrf *v;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 10:59:58 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2022-06-09 11:40:21 +02:00
|
|
|
|
|
|
|
int pim_show_upstream_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
|
|
|
|
pim_addr g, bool json)
|
|
|
|
{
|
|
|
|
pim_sgaddr sg = {0};
|
|
|
|
struct vrf *v;
|
|
|
|
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;
|
|
|
|
}
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 11:40:21 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
pim_show_upstream(pim, vty, &sg, json_parent);
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_upstream_vrf_all_helper(struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2022-06-09 11:57:49 +02:00
|
|
|
|
|
|
|
int pim_show_upstream_join_desired_helper(const char *vrf, struct vty *vty,
|
|
|
|
bool uj)
|
|
|
|
{
|
|
|
|
struct pim_instance *pim;
|
|
|
|
struct vrf *v;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 11:57:49 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
pim_show_join_desired(pim, vty, uj);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
2022-06-09 12:10:21 +02:00
|
|
|
|
|
|
|
int pim_show_upstream_rpf_helper(const char *vrf, struct vty *vty, bool uj)
|
|
|
|
{
|
|
|
|
struct pim_instance *pim;
|
|
|
|
struct vrf *v;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 12:10:21 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
pim_show_upstream_rpf(pim, vty, uj);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
2022-06-09 12:29:02 +02:00
|
|
|
|
|
|
|
int pim_show_state_helper(const char *vrf, struct vty *vty,
|
|
|
|
const char *s_or_g_str, const char *g_str, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 12:29:02 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_state_vrf_all_helper(struct vty *vty, const char *s_or_g_str,
|
|
|
|
const char *g_str, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2022-06-09 12:51:41 +02:00
|
|
|
|
|
|
|
int pim_show_multicast_helper(const char *vrf, struct vty *vty)
|
|
|
|
{
|
|
|
|
struct vrf *v;
|
|
|
|
struct pim_instance *pim;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 12:51:41 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
pim_cmd_show_ip_multicast_helper(pim, vty);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_multicast_vrf_all_helper(struct vty *vty)
|
|
|
|
{
|
|
|
|
struct vrf *vrf;
|
|
|
|
|
|
|
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
|
|
|
vty_out(vty, "VRF: %s\n", vrf->name);
|
|
|
|
pim_cmd_show_ip_multicast_helper(vrf->info, vty);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
2022-06-09 13:04:14 +02:00
|
|
|
|
|
|
|
int pim_show_multicast_count_helper(const char *vrf, struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 13:04:14 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
|
|
|
|
show_multicast_interfaces(pim, vty, json_parent);
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_multicast_count_vrf_all_helper(struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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_multicast_interfaces(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;
|
|
|
|
}
|
2022-06-09 13:27:20 +02:00
|
|
|
|
|
|
|
int pim_show_mroute_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
|
|
|
|
pim_addr g, bool fill, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 13:27:20 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_mroute_vrf_all_helper(struct vty *vty, bool fill, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2022-06-09 13:43:28 +02:00
|
|
|
|
|
|
|
int pim_show_mroute_count_helper(const char *vrf, struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 13:43:28 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
|
|
|
|
show_mroute_count(pim, vty, json_parent);
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_mroute_count_vrf_all_helper(struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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_count(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;
|
|
|
|
}
|
2022-06-09 13:53:12 +02:00
|
|
|
|
|
|
|
int pim_show_mroute_summary_helper(const char *vrf, struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-09 13:53:12 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
json_parent = json_object_new_object();
|
|
|
|
|
|
|
|
show_mroute_summary(pim, vty, json_parent);
|
|
|
|
|
|
|
|
if (json)
|
|
|
|
vty_json(vty, json_parent);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pim_show_mroute_summary_vrf_all_helper(struct vty *vty, bool json)
|
|
|
|
{
|
|
|
|
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_summary(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;
|
|
|
|
}
|
2022-05-27 07:11:12 +02:00
|
|
|
|
|
|
|
void pim_show_interface_traffic(struct pim_instance *pim, struct vty *vty,
|
|
|
|
bool uj)
|
|
|
|
{
|
|
|
|
struct interface *ifp = NULL;
|
|
|
|
struct pim_interface *pim_ifp = NULL;
|
|
|
|
json_object *json = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
json = json_object_new_object();
|
|
|
|
else {
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
|
|
|
|
"Interface", " HELLO", " JOIN",
|
|
|
|
" PRUNE", " REGISTER", "REGISTER-STOP",
|
|
|
|
" ASSERT", " BSM");
|
|
|
|
vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
|
|
|
|
" Rx/Tx", " Rx/Tx", " Rx/Tx",
|
|
|
|
" Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx");
|
|
|
|
vty_out(vty,
|
|
|
|
"---------------------------------------------------------------------------------------------------------------\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (uj) {
|
|
|
|
json_row = json_object_new_object();
|
|
|
|
json_object_pim_ifp_add(json_row, ifp);
|
|
|
|
json_object_int_add(json_row, "helloRx",
|
|
|
|
pim_ifp->pim_ifstat_hello_recv);
|
|
|
|
json_object_int_add(json_row, "helloTx",
|
|
|
|
pim_ifp->pim_ifstat_hello_sent);
|
|
|
|
json_object_int_add(json_row, "joinRx",
|
|
|
|
pim_ifp->pim_ifstat_join_recv);
|
|
|
|
json_object_int_add(json_row, "joinTx",
|
|
|
|
pim_ifp->pim_ifstat_join_send);
|
|
|
|
json_object_int_add(json_row, "pruneRx",
|
|
|
|
pim_ifp->pim_ifstat_prune_recv);
|
2022-07-11 13:13:29 +02:00
|
|
|
json_object_int_add(json_row, "pruneTx",
|
|
|
|
pim_ifp->pim_ifstat_prune_send);
|
2022-05-27 07:11:12 +02:00
|
|
|
json_object_int_add(json_row, "registerRx",
|
|
|
|
pim_ifp->pim_ifstat_reg_recv);
|
|
|
|
json_object_int_add(json_row, "registerTx",
|
|
|
|
pim_ifp->pim_ifstat_reg_send);
|
|
|
|
json_object_int_add(json_row, "registerStopRx",
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_recv);
|
|
|
|
json_object_int_add(json_row, "registerStopTx",
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_send);
|
|
|
|
json_object_int_add(json_row, "assertRx",
|
|
|
|
pim_ifp->pim_ifstat_assert_recv);
|
|
|
|
json_object_int_add(json_row, "assertTx",
|
|
|
|
pim_ifp->pim_ifstat_assert_send);
|
|
|
|
json_object_int_add(json_row, "bsmRx",
|
|
|
|
pim_ifp->pim_ifstat_bsm_rx);
|
|
|
|
json_object_int_add(json_row, "bsmTx",
|
|
|
|
pim_ifp->pim_ifstat_bsm_tx);
|
|
|
|
json_object_object_add(json, ifp->name, json_row);
|
|
|
|
} else {
|
|
|
|
vty_out(vty,
|
|
|
|
"%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
|
|
|
|
"/%-7" PRIu64 "\n",
|
|
|
|
ifp->name, pim_ifp->pim_ifstat_hello_recv,
|
|
|
|
pim_ifp->pim_ifstat_hello_sent,
|
|
|
|
pim_ifp->pim_ifstat_join_recv,
|
|
|
|
pim_ifp->pim_ifstat_join_send,
|
|
|
|
pim_ifp->pim_ifstat_prune_recv,
|
|
|
|
pim_ifp->pim_ifstat_prune_send,
|
|
|
|
pim_ifp->pim_ifstat_reg_recv,
|
|
|
|
pim_ifp->pim_ifstat_reg_send,
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_recv,
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_send,
|
|
|
|
pim_ifp->pim_ifstat_assert_recv,
|
|
|
|
pim_ifp->pim_ifstat_assert_send,
|
|
|
|
pim_ifp->pim_ifstat_bsm_rx,
|
|
|
|
pim_ifp->pim_ifstat_bsm_tx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (uj)
|
|
|
|
vty_json(vty, json);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pim_show_interface_traffic_single(struct pim_instance *pim,
|
|
|
|
struct vty *vty, const char *ifname,
|
|
|
|
bool uj)
|
|
|
|
{
|
|
|
|
struct interface *ifp = NULL;
|
|
|
|
struct pim_interface *pim_ifp = NULL;
|
|
|
|
json_object *json = NULL;
|
|
|
|
json_object *json_row = NULL;
|
|
|
|
uint8_t found_ifname = 0;
|
|
|
|
|
|
|
|
if (uj)
|
|
|
|
json = json_object_new_object();
|
|
|
|
else {
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
|
|
|
|
"Interface", " HELLO", " JOIN", " PRUNE",
|
|
|
|
" REGISTER", " REGISTER-STOP", " ASSERT",
|
|
|
|
" BSM");
|
|
|
|
vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
|
|
|
|
" Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
|
|
|
|
" Rx/Tx", " Rx/Tx", " Rx/Tx");
|
|
|
|
vty_out(vty,
|
|
|
|
"-------------------------------------------------------------------------------------------------------------------------------\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
if (strcmp(ifname, ifp->name))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
|
|
|
|
if (!pim_ifp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
found_ifname = 1;
|
|
|
|
if (uj) {
|
|
|
|
json_row = json_object_new_object();
|
|
|
|
json_object_pim_ifp_add(json_row, ifp);
|
|
|
|
json_object_int_add(json_row, "helloRx",
|
|
|
|
pim_ifp->pim_ifstat_hello_recv);
|
|
|
|
json_object_int_add(json_row, "helloTx",
|
|
|
|
pim_ifp->pim_ifstat_hello_sent);
|
|
|
|
json_object_int_add(json_row, "joinRx",
|
|
|
|
pim_ifp->pim_ifstat_join_recv);
|
|
|
|
json_object_int_add(json_row, "joinTx",
|
|
|
|
pim_ifp->pim_ifstat_join_send);
|
|
|
|
json_object_int_add(json_row, "pruneRx",
|
|
|
|
pim_ifp->pim_ifstat_prune_recv);
|
|
|
|
json_object_int_add(json_row, "pruneTx",
|
|
|
|
pim_ifp->pim_ifstat_prune_send);
|
|
|
|
json_object_int_add(json_row, "registerRx",
|
|
|
|
pim_ifp->pim_ifstat_reg_recv);
|
|
|
|
json_object_int_add(json_row, "registerTx",
|
|
|
|
pim_ifp->pim_ifstat_reg_send);
|
|
|
|
json_object_int_add(json_row, "registerStopRx",
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_recv);
|
|
|
|
json_object_int_add(json_row, "registerStopTx",
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_send);
|
|
|
|
json_object_int_add(json_row, "assertRx",
|
|
|
|
pim_ifp->pim_ifstat_assert_recv);
|
|
|
|
json_object_int_add(json_row, "assertTx",
|
|
|
|
pim_ifp->pim_ifstat_assert_send);
|
|
|
|
json_object_int_add(json_row, "bsmRx",
|
|
|
|
pim_ifp->pim_ifstat_bsm_rx);
|
|
|
|
json_object_int_add(json_row, "bsmTx",
|
|
|
|
pim_ifp->pim_ifstat_bsm_tx);
|
|
|
|
|
|
|
|
json_object_object_add(json, ifp->name, json_row);
|
|
|
|
} else {
|
|
|
|
vty_out(vty,
|
|
|
|
"%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
|
|
|
|
"/%-7" PRIu64 "\n",
|
|
|
|
ifp->name, pim_ifp->pim_ifstat_hello_recv,
|
|
|
|
pim_ifp->pim_ifstat_hello_sent,
|
|
|
|
pim_ifp->pim_ifstat_join_recv,
|
|
|
|
pim_ifp->pim_ifstat_join_send,
|
|
|
|
pim_ifp->pim_ifstat_prune_recv,
|
|
|
|
pim_ifp->pim_ifstat_prune_send,
|
|
|
|
pim_ifp->pim_ifstat_reg_recv,
|
|
|
|
pim_ifp->pim_ifstat_reg_send,
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_recv,
|
|
|
|
pim_ifp->pim_ifstat_reg_stop_send,
|
|
|
|
pim_ifp->pim_ifstat_assert_recv,
|
|
|
|
pim_ifp->pim_ifstat_assert_send,
|
|
|
|
pim_ifp->pim_ifstat_bsm_rx,
|
|
|
|
pim_ifp->pim_ifstat_bsm_tx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (uj)
|
|
|
|
vty_json(vty, json);
|
|
|
|
else if (!found_ifname)
|
|
|
|
vty_out(vty, "%% No such interface\n");
|
|
|
|
}
|
2022-06-01 17:58:33 +02:00
|
|
|
|
|
|
|
int pim_show_interface_traffic_helper(const char *vrf, const char *if_name,
|
|
|
|
struct vty *vty, bool uj)
|
|
|
|
{
|
|
|
|
struct pim_instance *pim;
|
|
|
|
struct vrf *v;
|
|
|
|
|
|
|
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
2022-07-12 15:00:57 +02:00
|
|
|
pim = v->info;
|
2022-06-01 17:58:33 +02:00
|
|
|
|
|
|
|
if (!pim) {
|
|
|
|
vty_out(vty, "%% Unable to find pim instance\n");
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (if_name)
|
|
|
|
pim_show_interface_traffic_single(v->info, vty, if_name, uj);
|
|
|
|
else
|
|
|
|
pim_show_interface_traffic(v->info, vty, uj);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
2022-07-19 08:44:47 +02:00
|
|
|
|
|
|
|
void clear_pim_interfaces(struct pim_instance *pim)
|
|
|
|
{
|
|
|
|
struct interface *ifp;
|
|
|
|
|
|
|
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
|
|
|
if (ifp->info)
|
|
|
|
pim_neighbor_delete_all(ifp, "interface cleared");
|
|
|
|
}
|
|
|
|
}
|