mirror_frr/vrrpd/vrrp_vty.c
Quentin Young 23804b4f04 vrrpd: display primary address in json output
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>
2019-05-17 00:27:08 +00:00

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