mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-06-02 23:35:10 +00:00

And also, fill in the non-json output with a :: for the v6 primary since we're letting the operating system select which one it wants to use and we don't actually know what our primary address is. Another thing to revisit in the future... Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
662 lines
20 KiB
C
662 lines
20 KiB
C
/*
|
|
* VRRP CLI commands.
|
|
* Copyright (C) 2018-2019 Cumulus Networks, Inc.
|
|
* Quentin Young
|
|
*
|
|
* 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/command.h"
|
|
#include "lib/if.h"
|
|
#include "lib/ipaddr.h"
|
|
#include "lib/json.h"
|
|
#include "lib/prefix.h"
|
|
#include "lib/termtable.h"
|
|
#include "lib/vty.h"
|
|
|
|
#include "vrrp.h"
|
|
#include "vrrp_debug.h"
|
|
#include "vrrp_memory.h"
|
|
#include "vrrp_vty.h"
|
|
#ifndef VTYSH_EXTRACT_PL
|
|
#include "vrrpd/vrrp_vty_clippy.c"
|
|
#endif
|
|
|
|
|
|
#define VRRP_STR "Virtual Router Redundancy Protocol\n"
|
|
#define VRRP_VRID_STR "Virtual Router ID\n"
|
|
#define VRRP_PRIORITY_STR "Virtual Router Priority\n"
|
|
#define VRRP_ADVINT_STR "Virtual Router Advertisement Interval\n"
|
|
#define VRRP_IP_STR "Virtual Router IPv4 address\n"
|
|
#define VRRP_VERSION_STR "VRRP protocol version\n"
|
|
|
|
#define VROUTER_GET_VTY(_vty, _ifp, _vrid, _vr) \
|
|
do { \
|
|
_vr = vrrp_lookup(_ifp, _vrid); \
|
|
if (!_vr) { \
|
|
vty_out(_vty, \
|
|
"%% Please configure VRRP instance %u\n", \
|
|
(unsigned int)_vrid); \
|
|
return CMD_WARNING_CONFIG_FAILED; \
|
|
} \
|
|
} while (0);
|
|
|
|
/* clang-format off */
|
|
|
|
DEFPY(vrrp_vrid,
|
|
vrrp_vrid_cmd,
|
|
"[no] vrrp (1-255)$vrid [version (2-3)]",
|
|
NO_STR
|
|
VRRP_STR
|
|
VRRP_VRID_STR
|
|
VRRP_VERSION_STR
|
|
VRRP_VERSION_STR)
|
|
{
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
struct vrrp_vrouter *vr = vrrp_lookup(ifp, vrid);
|
|
|
|
if (version == 0)
|
|
version = 3;
|
|
|
|
if (no && vr)
|
|
vrrp_vrouter_destroy(vr);
|
|
else if (no && !vr)
|
|
vty_out(vty, "%% VRRP instance %ld does not exist on %s\n",
|
|
vrid, ifp->name);
|
|
else if (!vr)
|
|
vrrp_vrouter_create(ifp, vrid, version);
|
|
else if (vr)
|
|
vty_out(vty, "%% VRRP instance %ld already exists on %s\n",
|
|
vrid, ifp->name);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFPY(vrrp_shutdown,
|
|
vrrp_shutdown_cmd,
|
|
"[no] vrrp (1-255)$vrid shutdown",
|
|
NO_STR
|
|
VRRP_STR
|
|
VRRP_VRID_STR
|
|
"Force VRRP router into administrative shutdown\n")
|
|
{
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
struct vrrp_vrouter *vr;
|
|
|
|
VROUTER_GET_VTY(vty, ifp, vrid, vr);
|
|
|
|
if (!no) {
|
|
if (vr->v4->fsm.state != VRRP_STATE_INITIALIZE)
|
|
vrrp_event(vr->v4, VRRP_EVENT_SHUTDOWN);
|
|
if (vr->v6->fsm.state != VRRP_STATE_INITIALIZE)
|
|
vrrp_event(vr->v6, VRRP_EVENT_SHUTDOWN);
|
|
vr->shutdown = true;
|
|
} else {
|
|
vr->shutdown = false;
|
|
vrrp_check_start(vr);
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFPY(vrrp_priority,
|
|
vrrp_priority_cmd,
|
|
"[no] vrrp (1-255)$vrid priority (1-254)",
|
|
NO_STR
|
|
VRRP_STR
|
|
VRRP_VRID_STR
|
|
VRRP_PRIORITY_STR
|
|
"Priority value")
|
|
{
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
struct vrrp_vrouter *vr;
|
|
uint8_t newprio = no ? vd.priority : priority;
|
|
|
|
VROUTER_GET_VTY(vty, ifp, vrid, vr);
|
|
|
|
vrrp_set_priority(vr, newprio);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFPY(vrrp_advertisement_interval,
|
|
vrrp_advertisement_interval_cmd,
|
|
"[no] vrrp (1-255)$vrid advertisement-interval (1-4096)",
|
|
NO_STR VRRP_STR VRRP_VRID_STR VRRP_ADVINT_STR
|
|
"Advertisement interval in centiseconds")
|
|
{
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
struct vrrp_vrouter *vr;
|
|
uint16_t newadvint = no ? vd.advertisement_interval :
|
|
advertisement_interval;
|
|
|
|
VROUTER_GET_VTY(vty, ifp, vrid, vr);
|
|
vrrp_set_advertisement_interval(vr, newadvint);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFPY(vrrp_ip,
|
|
vrrp_ip_cmd,
|
|
"[no] vrrp (1-255)$vrid ip A.B.C.D",
|
|
NO_STR
|
|
VRRP_STR
|
|
VRRP_VRID_STR
|
|
"Add IPv4 address\n"
|
|
VRRP_IP_STR)
|
|
{
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
struct vrrp_vrouter *vr;
|
|
bool deactivated = false;
|
|
bool activated = false;
|
|
bool failed = false;
|
|
int ret = CMD_SUCCESS;
|
|
|
|
VROUTER_GET_VTY(vty, ifp, vrid, vr);
|
|
|
|
bool will_activate = (vr->v4->fsm.state == VRRP_STATE_INITIALIZE);
|
|
|
|
if (no) {
|
|
int oldstate = vr->v4->fsm.state;
|
|
failed = vrrp_del_ipv4(vr, ip);
|
|
vrrp_check_start(vr);
|
|
deactivated = (vr->v4->fsm.state == VRRP_STATE_INITIALIZE
|
|
&& oldstate != VRRP_STATE_INITIALIZE);
|
|
} else {
|
|
int oldstate = vr->v4->fsm.state;
|
|
failed = vrrp_add_ipv4(vr, ip);
|
|
vrrp_check_start(vr);
|
|
activated = (vr->v4->fsm.state != VRRP_STATE_INITIALIZE
|
|
&& oldstate == VRRP_STATE_INITIALIZE);
|
|
}
|
|
|
|
if (activated)
|
|
vty_out(vty, "%% Activated IPv4 Virtual Router %ld\n", vrid);
|
|
if (deactivated)
|
|
vty_out(vty, "%% Deactivated IPv4 Virtual Router %ld\n", vrid);
|
|
if (failed) {
|
|
vty_out(vty, "%% Failed to %s virtual IP\n",
|
|
no ? "remove" : "add");
|
|
ret = CMD_WARNING_CONFIG_FAILED;
|
|
if (will_activate && !activated) {
|
|
vty_out(vty,
|
|
"%% Failed to activate IPv4 Virtual Router %ld\n",
|
|
vrid);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
DEFPY(vrrp_ip6,
|
|
vrrp_ip6_cmd,
|
|
"[no] vrrp (1-255)$vrid ipv6 X:X::X:X",
|
|
NO_STR
|
|
VRRP_STR
|
|
VRRP_VRID_STR
|
|
"Add IPv6 address\n"
|
|
VRRP_IP_STR)
|
|
{
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
struct vrrp_vrouter *vr;
|
|
bool deactivated = false;
|
|
bool activated = false;
|
|
bool failed = false;
|
|
int ret = CMD_SUCCESS;
|
|
|
|
VROUTER_GET_VTY(vty, ifp, vrid, vr);
|
|
|
|
if (vr->version != 3) {
|
|
vty_out(vty,
|
|
"%% Cannot add IPv6 address to VRRPv2 virtual router\n");
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
}
|
|
|
|
bool will_activate = (vr->v6->fsm.state == VRRP_STATE_INITIALIZE);
|
|
|
|
if (no) {
|
|
int oldstate = vr->v6->fsm.state;
|
|
failed = vrrp_del_ipv6(vr, ipv6);
|
|
vrrp_check_start(vr);
|
|
deactivated = (vr->v6->fsm.state == VRRP_STATE_INITIALIZE
|
|
&& oldstate != VRRP_STATE_INITIALIZE);
|
|
} else {
|
|
int oldstate = vr->v6->fsm.state;
|
|
failed = vrrp_add_ipv6(vr, ipv6);
|
|
vrrp_check_start(vr);
|
|
activated = (vr->v6->fsm.state != VRRP_STATE_INITIALIZE
|
|
&& oldstate == VRRP_STATE_INITIALIZE);
|
|
}
|
|
|
|
if (activated)
|
|
vty_out(vty, "%% Activated IPv6 Virtual Router %ld\n", vrid);
|
|
if (deactivated)
|
|
vty_out(vty, "%% Deactivated IPv6 Virtual Router %ld\n", vrid);
|
|
if (failed) {
|
|
vty_out(vty, "%% Failed to %s virtual IP\n",
|
|
no ? "remove" : "add");
|
|
ret = CMD_WARNING_CONFIG_FAILED;
|
|
if (will_activate && !activated) {
|
|
vty_out(vty,
|
|
"%% Failed to activate IPv6 Virtual Router %ld\n",
|
|
vrid);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
DEFPY(vrrp_preempt,
|
|
vrrp_preempt_cmd,
|
|
"[no] vrrp (1-255)$vrid preempt",
|
|
NO_STR
|
|
VRRP_STR
|
|
VRRP_VRID_STR
|
|
"Preempt mode\n")
|
|
{
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
struct vrrp_vrouter *vr;
|
|
|
|
VROUTER_GET_VTY(vty, ifp, vrid, vr);
|
|
|
|
vr->preempt_mode = !no;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFPY(vrrp_autoconfigure,
|
|
vrrp_autoconfigure_cmd,
|
|
"[no] vrrp autoconfigure [version (2-3)]",
|
|
NO_STR
|
|
VRRP_STR
|
|
"Automatically set up VRRP instances on VRRP-compatible interfaces\n"
|
|
"Version for automatically configured instances\n"
|
|
VRRP_VERSION_STR)
|
|
{
|
|
version = version ? version : 3;
|
|
|
|
if (!no)
|
|
vrrp_autoconfig_on(version);
|
|
else
|
|
vrrp_autoconfig_off();
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFPY(vrrp_default,
|
|
vrrp_default_cmd,
|
|
"[no] vrrp default <advertisement-interval$adv (1-4096)$advint|preempt$p|priority$prio (1-254)$prioval|shutdown$s>",
|
|
NO_STR
|
|
VRRP_STR
|
|
"Configure defaults for new VRRP instances\n"
|
|
VRRP_ADVINT_STR
|
|
"Advertisement interval in centiseconds\n"
|
|
"Preempt mode\n"
|
|
VRRP_PRIORITY_STR
|
|
"Priority value\n"
|
|
"Force VRRP router into administrative shutdown\n")
|
|
{
|
|
if (adv)
|
|
vd.advertisement_interval = no ? VRRP_DEFAULT_ADVINT : advint;
|
|
if (p)
|
|
vd.preempt_mode = !no;
|
|
if (prio)
|
|
vd.priority = no ? VRRP_DEFAULT_PRIORITY : prioval;
|
|
if (s)
|
|
vd.shutdown = !no;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* clang-format on */
|
|
|
|
/*
|
|
* Build JSON representation of VRRP instance.
|
|
*
|
|
* vr
|
|
* VRRP router to build json object from
|
|
*
|
|
* Returns:
|
|
* JSON representation of VRRP instance. Must be freed by caller.
|
|
*/
|
|
static struct json_object *vrrp_build_json(struct vrrp_vrouter *vr)
|
|
{
|
|
char ethstr4[ETHER_ADDR_STRLEN];
|
|
char ethstr6[ETHER_ADDR_STRLEN];
|
|
char ipstr[INET6_ADDRSTRLEN];
|
|
const char *stastr4 = vrrp_state_names[vr->v4->fsm.state];
|
|
const char *stastr6 = vrrp_state_names[vr->v6->fsm.state];
|
|
char sipstr4[INET6_ADDRSTRLEN] = {};
|
|
char sipstr6[INET6_ADDRSTRLEN] = {};
|
|
struct listnode *ln;
|
|
struct ipaddr *ip;
|
|
struct json_object *j = json_object_new_object();
|
|
struct json_object *v4 = json_object_new_object();
|
|
struct json_object *v4_stats = json_object_new_object();
|
|
struct json_object *v4_addrs = json_object_new_array();
|
|
struct json_object *v6 = json_object_new_object();
|
|
struct json_object *v6_stats = json_object_new_object();
|
|
struct json_object *v6_addrs = json_object_new_array();
|
|
|
|
prefix_mac2str(&vr->v4->vmac, ethstr4, sizeof(ethstr4));
|
|
prefix_mac2str(&vr->v6->vmac, ethstr6, sizeof(ethstr6));
|
|
|
|
json_object_int_add(j, "vrid", vr->vrid);
|
|
json_object_int_add(j, "version", vr->version);
|
|
json_object_boolean_add(j, "autoconfigured", vr->autoconf);
|
|
json_object_boolean_add(j, "shutdown", vr->shutdown);
|
|
json_object_boolean_add(j, "preemptMode", vr->preempt_mode);
|
|
json_object_boolean_add(j, "acceptMode", vr->accept_mode);
|
|
json_object_string_add(j, "interface", vr->ifp->name);
|
|
/* v4 */
|
|
json_object_string_add(v4, "interface",
|
|
vr->v4->mvl_ifp ? vr->v4->mvl_ifp->name : "");
|
|
json_object_string_add(v4, "vmac", ethstr4);
|
|
ipaddr2str(&vr->v4->src, sipstr4, sizeof(sipstr4));
|
|
json_object_string_add(v4, "primaryAddress", sipstr4);
|
|
json_object_string_add(v4, "status", stastr4);
|
|
json_object_int_add(v4, "effectivePriority", vr->v4->priority);
|
|
json_object_int_add(v4, "masterAdverInterval",
|
|
vr->v4->master_adver_interval);
|
|
json_object_int_add(v4, "skewTime", vr->v4->skew_time);
|
|
json_object_int_add(v4, "masterDownInterval",
|
|
vr->v4->master_down_interval);
|
|
/* v4 stats */
|
|
json_object_int_add(v4_stats, "adverTx", vr->v4->stats.adver_tx_cnt);
|
|
json_object_int_add(v4_stats, "adverRx", vr->v4->stats.adver_rx_cnt);
|
|
json_object_int_add(v4_stats, "garpTx", vr->v4->stats.garp_tx_cnt);
|
|
json_object_int_add(v4_stats, "transitions", vr->v4->stats.trans_cnt);
|
|
json_object_object_add(v4, "stats", v4_stats);
|
|
/* v4 addrs */
|
|
if (vr->v4->addrs->count) {
|
|
for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ln, ip)) {
|
|
inet_ntop(vr->v4->family, &ip->ipaddr_v4, ipstr,
|
|
sizeof(ipstr));
|
|
json_object_array_add(v4_addrs,
|
|
json_object_new_string(ipstr));
|
|
}
|
|
}
|
|
json_object_object_add(v4, "addresses", v4_addrs);
|
|
json_object_object_add(j, "v4", v4);
|
|
|
|
/* v6 */
|
|
json_object_string_add(v6, "interface",
|
|
vr->v6->mvl_ifp ? vr->v6->mvl_ifp->name : "");
|
|
json_object_string_add(v6, "vmac", ethstr6);
|
|
ipaddr2str(&vr->v6->src, sipstr6, sizeof(sipstr6));
|
|
if (strlen(sipstr6) == 0 && vr->v6->src.ip.addr == 0x00)
|
|
strlcat(sipstr6, "::", sizeof(sipstr6));
|
|
json_object_string_add(v6, "primaryAddress", sipstr6);
|
|
json_object_string_add(v6, "status", stastr6);
|
|
json_object_int_add(v6, "effectivePriority", vr->v6->priority);
|
|
json_object_int_add(v6, "masterAdverInterval",
|
|
vr->v6->master_adver_interval);
|
|
json_object_int_add(v6, "skewTime", vr->v6->skew_time);
|
|
json_object_int_add(v6, "masterDownInterval",
|
|
vr->v6->master_down_interval);
|
|
/* v6 stats */
|
|
json_object_int_add(v6_stats, "adverTx", vr->v6->stats.adver_tx_cnt);
|
|
json_object_int_add(v6_stats, "adverRx", vr->v6->stats.adver_rx_cnt);
|
|
json_object_int_add(v6_stats, "neighborAdverTx",
|
|
vr->v6->stats.una_tx_cnt);
|
|
json_object_int_add(v6_stats, "transitions", vr->v6->stats.trans_cnt);
|
|
json_object_object_add(v6, "stats", v6_stats);
|
|
/* v6 addrs */
|
|
if (vr->v6->addrs->count) {
|
|
for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ln, ip)) {
|
|
inet_ntop(vr->v6->family, &ip->ipaddr_v6, ipstr,
|
|
sizeof(ipstr));
|
|
json_object_array_add(v6_addrs,
|
|
json_object_new_string(ipstr));
|
|
}
|
|
}
|
|
json_object_object_add(v6, "addresses", v6_addrs);
|
|
json_object_object_add(j, "v6", v6);
|
|
|
|
return j;
|
|
}
|
|
|
|
/*
|
|
* Dump VRRP instance status to VTY.
|
|
*
|
|
* vty
|
|
* vty to dump to
|
|
*
|
|
* vr
|
|
* VRRP router to dump
|
|
*/
|
|
static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
|
|
{
|
|
char ethstr4[ETHER_ADDR_STRLEN];
|
|
char ethstr6[ETHER_ADDR_STRLEN];
|
|
char ipstr[INET6_ADDRSTRLEN];
|
|
const char *stastr4 = vrrp_state_names[vr->v4->fsm.state];
|
|
const char *stastr6 = vrrp_state_names[vr->v6->fsm.state];
|
|
char sipstr4[INET6_ADDRSTRLEN] = {};
|
|
char sipstr6[INET6_ADDRSTRLEN] = {};
|
|
struct listnode *ln;
|
|
struct ipaddr *ip;
|
|
|
|
struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
|
|
|
ttable_add_row(tt, "%s|%" PRIu32, "Virtual Router ID", vr->vrid);
|
|
ttable_add_row(tt, "%s|%" PRIu8, "Protocol Version", vr->version);
|
|
ttable_add_row(tt, "%s|%s", "Autoconfigured",
|
|
vr->autoconf ? "Yes" : "No");
|
|
ttable_add_row(tt, "%s|%s", "Shutdown", vr->shutdown ? "Yes" : "No");
|
|
ttable_add_row(tt, "%s|%s", "Interface", vr->ifp->name);
|
|
prefix_mac2str(&vr->v4->vmac, ethstr4, sizeof(ethstr4));
|
|
prefix_mac2str(&vr->v6->vmac, ethstr6, sizeof(ethstr6));
|
|
ttable_add_row(tt, "%s|%s", "VRRP interface (v4)",
|
|
vr->v4->mvl_ifp ? vr->v4->mvl_ifp->name : "None");
|
|
ttable_add_row(tt, "%s|%s", "VRRP interface (v6)",
|
|
vr->v6->mvl_ifp ? vr->v6->mvl_ifp->name : "None");
|
|
ipaddr2str(&vr->v4->src, sipstr4, sizeof(sipstr4));
|
|
ipaddr2str(&vr->v6->src, sipstr6, sizeof(sipstr6));
|
|
if (strlen(sipstr6) == 0 && vr->v6->src.ip.addr == 0x00)
|
|
strlcat(sipstr6, "::", sizeof(sipstr6));
|
|
ttable_add_row(tt, "%s|%s", "Primary IP (v4)", sipstr4);
|
|
ttable_add_row(tt, "%s|%s", "Primary IP (v6)", sipstr6);
|
|
ttable_add_row(tt, "%s|%s", "Virtual MAC (v4)", ethstr4);
|
|
ttable_add_row(tt, "%s|%s", "Virtual MAC (v6)", ethstr6);
|
|
ttable_add_row(tt, "%s|%s", "Status (v4)", stastr4);
|
|
ttable_add_row(tt, "%s|%s", "Status (v6)", stastr6);
|
|
ttable_add_row(tt, "%s|%" PRIu8, "Priority", vr->priority);
|
|
ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v4)",
|
|
vr->v4->priority);
|
|
ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v6)",
|
|
vr->v6->priority);
|
|
ttable_add_row(tt, "%s|%s", "Preempt Mode",
|
|
vr->preempt_mode ? "Yes" : "No");
|
|
ttable_add_row(tt, "%s|%s", "Accept Mode",
|
|
vr->accept_mode ? "Yes" : "No");
|
|
ttable_add_row(tt, "%s|%" PRIu16 " cs", "Advertisement Interval",
|
|
vr->advertisement_interval);
|
|
ttable_add_row(tt, "%s|%" PRIu16 " cs",
|
|
"Master Advertisement Interval (v4)",
|
|
vr->v4->master_adver_interval);
|
|
ttable_add_row(tt, "%s|%" PRIu16 " cs",
|
|
"Master Advertisement Interval (v6)",
|
|
vr->v6->master_adver_interval);
|
|
ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Tx (v4)",
|
|
vr->v4->stats.adver_tx_cnt);
|
|
ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Tx (v6)",
|
|
vr->v6->stats.adver_tx_cnt);
|
|
ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Rx (v4)",
|
|
vr->v4->stats.adver_rx_cnt);
|
|
ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Rx (v6)",
|
|
vr->v6->stats.adver_rx_cnt);
|
|
ttable_add_row(tt, "%s|%" PRIu32, "Gratuitous ARP Tx (v4)",
|
|
vr->v4->stats.garp_tx_cnt);
|
|
ttable_add_row(tt, "%s|%" PRIu32, "Neigh. Adverts Tx (v6)",
|
|
vr->v6->stats.una_tx_cnt);
|
|
ttable_add_row(tt, "%s|%" PRIu32, "State transitions (v4)",
|
|
vr->v4->stats.trans_cnt);
|
|
ttable_add_row(tt, "%s|%" PRIu32, "State transitions (v6)",
|
|
vr->v6->stats.trans_cnt);
|
|
ttable_add_row(tt, "%s|%" PRIu16 " cs", "Skew Time (v4)",
|
|
vr->v4->skew_time);
|
|
ttable_add_row(tt, "%s|%" PRIu16 " cs", "Skew Time (v6)",
|
|
vr->v6->skew_time);
|
|
ttable_add_row(tt, "%s|%" PRIu16 " cs", "Master Down Interval (v4)",
|
|
vr->v4->master_down_interval);
|
|
ttable_add_row(tt, "%s|%" PRIu16 " cs", "Master Down Interval (v6)",
|
|
vr->v6->master_down_interval);
|
|
ttable_add_row(tt, "%s|%u", "IPv4 Addresses", vr->v4->addrs->count);
|
|
|
|
char fill[35];
|
|
memset(fill, '.', sizeof(fill));
|
|
fill[sizeof(fill) - 1] = 0x00;
|
|
if (vr->v4->addrs->count) {
|
|
for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ln, ip)) {
|
|
inet_ntop(vr->v4->family, &ip->ipaddr_v4, ipstr,
|
|
sizeof(ipstr));
|
|
ttable_add_row(tt, "%s|%s", fill, ipstr);
|
|
}
|
|
}
|
|
|
|
ttable_add_row(tt, "%s|%u", "IPv6 Addresses", vr->v6->addrs->count);
|
|
|
|
if (vr->v6->addrs->count) {
|
|
for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ln, ip)) {
|
|
inet_ntop(vr->v6->family, &ip->ipaddr_v6, ipstr,
|
|
sizeof(ipstr));
|
|
ttable_add_row(tt, "%s|%s", fill, ipstr);
|
|
}
|
|
}
|
|
|
|
char *table = ttable_dump(tt, "\n");
|
|
vty_out(vty, "\n%s\n", table);
|
|
XFREE(MTYPE_TMP, table);
|
|
ttable_del(tt);
|
|
}
|
|
|
|
/* clang-format off */
|
|
|
|
DEFPY(vrrp_vrid_show,
|
|
vrrp_vrid_show_cmd,
|
|
"show vrrp [interface INTERFACE$ifn] [(1-255)$vrid] [json$json]",
|
|
SHOW_STR
|
|
VRRP_STR
|
|
INTERFACE_STR
|
|
"Only show VRRP instances on this interface\n"
|
|
VRRP_VRID_STR
|
|
JSON_STR)
|
|
{
|
|
struct vrrp_vrouter *vr;
|
|
struct listnode *ln;
|
|
struct list *ll = hash_to_list(vrrp_vrouters_hash);
|
|
struct json_object *j = json_object_new_array();
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(ll, ln, vr)) {
|
|
if (ifn && !strmatch(ifn, vr->ifp->name))
|
|
continue;
|
|
if (vrid && ((uint8_t) vrid) != vr->vrid)
|
|
continue;
|
|
|
|
if (!json)
|
|
vrrp_show(vty, vr);
|
|
else
|
|
json_object_array_add(j, vrrp_build_json(vr));
|
|
}
|
|
|
|
if (json)
|
|
vty_out(vty, "%s\n",
|
|
json_object_to_json_string_ext(
|
|
j, JSON_C_TO_STRING_PRETTY));
|
|
|
|
json_object_free(j);
|
|
|
|
list_delete(&ll);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
|
|
DEFPY(debug_vrrp,
|
|
debug_vrrp_cmd,
|
|
"[no] debug vrrp [{protocol$proto|autoconfigure$ac|packets$pkt|sockets$sock|ndisc$ndisc|arp$arp|zebra$zebra}]",
|
|
NO_STR
|
|
DEBUG_STR
|
|
VRRP_STR
|
|
"Debug protocol state\n"
|
|
"Debug autoconfiguration\n"
|
|
"Debug sent and received packets\n"
|
|
"Debug socket creation and configuration\n"
|
|
"Debug Neighbor Discovery\n"
|
|
"Debug ARP\n"
|
|
"Debug Zebra events\n")
|
|
{
|
|
/* If no specific are given on/off them all */
|
|
if (strmatch(argv[argc - 1]->text, "vrrp"))
|
|
vrrp_debug_set(NULL, 0, vty->node, !no, true, true, true, true,
|
|
true, true, true);
|
|
else
|
|
vrrp_debug_set(NULL, 0, vty->node, !no, !!proto, !!ac, !!pkt,
|
|
!!sock, !!ndisc, !!arp, !!zebra);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN_NOSH (show_debugging_vrrp,
|
|
show_debugging_vrrp_cmd,
|
|
"show debugging [vrrp]",
|
|
SHOW_STR
|
|
DEBUG_STR
|
|
"VRRP information\n")
|
|
{
|
|
vty_out(vty, "VRRP debugging status:\n");
|
|
|
|
vrrp_debug_status_write(vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* clang-format on */
|
|
|
|
static struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1};
|
|
static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
|
|
static struct cmd_node vrrp_node = {VRRP_NODE, "", 1};
|
|
|
|
void vrrp_vty_init(void)
|
|
{
|
|
install_node(&debug_node, vrrp_config_write_debug);
|
|
install_node(&interface_node, vrrp_config_write_interface);
|
|
install_node(&vrrp_node, vrrp_config_write_global);
|
|
if_cmd_init();
|
|
|
|
install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
|
|
install_element(VIEW_NODE, &show_debugging_vrrp_cmd);
|
|
install_element(VIEW_NODE, &debug_vrrp_cmd);
|
|
install_element(CONFIG_NODE, &debug_vrrp_cmd);
|
|
install_element(CONFIG_NODE, &vrrp_autoconfigure_cmd);
|
|
install_element(CONFIG_NODE, &vrrp_default_cmd);
|
|
install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
|
|
install_element(INTERFACE_NODE, &vrrp_shutdown_cmd);
|
|
install_element(INTERFACE_NODE, &vrrp_priority_cmd);
|
|
install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd);
|
|
install_element(INTERFACE_NODE, &vrrp_ip_cmd);
|
|
install_element(INTERFACE_NODE, &vrrp_ip6_cmd);
|
|
install_element(INTERFACE_NODE, &vrrp_preempt_cmd);
|
|
}
|