#include "vrrp.h"
#include "vrrp_debug.h"
-#include "vrrp_memory.h"
#include "vrrp_vty.h"
+#include "vrrp_zebra.h"
#ifndef VTYSH_EXTRACT_PL
#include "vrrpd/vrrp_vty_clippy.c"
#endif
(unsigned int)_vrid); \
return CMD_WARNING_CONFIG_FAILED; \
} \
- } while (0);
+ } while (0)
/* clang-format off */
DEFPY(vrrp_advertisement_interval,
vrrp_advertisement_interval_cmd,
- "[no] vrrp (1-255)$vrid advertisement-interval (1-4096)",
+ "[no] vrrp (1-255)$vrid advertisement-interval (10-40950)",
NO_STR VRRP_STR VRRP_VRID_STR VRRP_ADVINT_STR
- "Advertisement interval in centiseconds")
+ "Advertisement interval in milliseconds; must be multiple of 10")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct vrrp_vrouter *vr;
- uint16_t newadvint = no ? vd.advertisement_interval :
- advertisement_interval;
+ uint16_t newadvint =
+ no ? vd.advertisement_interval * CS2MS : advertisement_interval;
+
+ if (newadvint % CS2MS != 0) {
+ vty_out(vty, "%% Value must be a multiple of %u\n",
+ (unsigned int)CS2MS);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* all internal computations are in centiseconds */
+ newadvint /= CS2MS;
VROUTER_GET_VTY(vty, ifp, vrid, vr);
vrrp_set_advertisement_interval(vr, newadvint);
bool activated = false;
bool failed = false;
int ret = CMD_SUCCESS;
+ int oldstate;
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;
+ 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;
+ oldstate = vr->v4->fsm.state;
failed = vrrp_add_ipv4(vr, ip);
vrrp_check_start(vr);
activated = (vr->v4->fsm.state != VRRP_STATE_INITIALIZE
bool activated = false;
bool failed = false;
int ret = CMD_SUCCESS;
+ int oldstate;
VROUTER_GET_VTY(vty, ifp, vrid, vr);
bool will_activate = (vr->v6->fsm.state == VRRP_STATE_INITIALIZE);
if (no) {
- int oldstate = vr->v6->fsm.state;
+ 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;
+ 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);
}
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] vrrp default <advertisement-interval$adv (10-40950)$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"
+ "Advertisement interval in milliseconds\n"
"Preempt mode\n"
VRRP_PRIORITY_STR
"Priority value\n"
"Force VRRP router into administrative shutdown\n")
{
- if (adv)
+ if (adv) {
+ if (advint % CS2MS != 0) {
+ vty_out(vty, "%% Value must be a multiple of %u\n",
+ (unsigned int)CS2MS);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* all internal computations are in centiseconds */
+ advint /= CS2MS;
vd.advertisement_interval = no ? VRRP_DEFAULT_ADVINT : advint;
+ }
if (p)
vd.preempt_mode = !no;
if (prio)
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();
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);
+ json_object_int_add(j, "advertisementInterval",
+ vr->advertisement_interval * CS2MS);
/* 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);
+ vr->v4->master_adver_interval * CS2MS);
+ json_object_int_add(v4, "skewTime", vr->v4->skew_time * CS2MS);
json_object_int_add(v4, "masterDownInterval",
- vr->v4->master_down_interval);
+ vr->v4->master_down_interval * CS2MS);
/* 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_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);
+ vr->v6->master_adver_interval * CS2MS);
+ json_object_int_add(v6, "skewTime", vr->v6->skew_time * CS2MS);
json_object_int_add(v6, "masterDownInterval",
- vr->v6->master_down_interval);
+ vr->v6->master_down_interval * CS2MS);
/* 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);
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;
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);
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",
+ ttable_add_row(tt, "%s|%d ms", "Advertisement Interval",
+ vr->advertisement_interval * CS2MS);
+ ttable_add_row(tt, "%s|%d ms",
"Master Advertisement Interval (v4)",
- vr->v4->master_adver_interval);
- ttable_add_row(tt, "%s|%" PRIu16 " cs",
+ vr->v4->master_adver_interval * CS2MS);
+ ttable_add_row(tt, "%s|%d ms",
"Master Advertisement Interval (v6)",
- vr->v6->master_adver_interval);
+ vr->v6->master_adver_interval * CS2MS);
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->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|%d ms", "Skew Time (v4)",
+ vr->v4->skew_time * CS2MS);
+ ttable_add_row(tt, "%s|%d ms", "Skew Time (v6)",
+ vr->v6->skew_time * CS2MS);
+ ttable_add_row(tt, "%s|%d ms", "Master Down Interval (v4)",
+ vr->v4->master_down_interval * CS2MS);
+ ttable_add_row(tt, "%s|%d ms", "Master Down Interval (v6)",
+ vr->v6->master_down_interval * CS2MS);
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) {
}
char *table = ttable_dump(tt, "\n");
+
vty_out(vty, "\n%s\n", table);
XFREE(MTYPE_TMP, table);
ttable_del(tt);
}
+/*
+ * Sort comparator, used when sorting VRRP instances for display purposes.
+ *
+ * Sorts by interface name first, then by VRID ascending.
+ */
+static int vrrp_instance_display_sort_cmp(const void **d1, const void **d2)
+{
+ const struct vrrp_vrouter *vr1 = *d1;
+ const struct vrrp_vrouter *vr2 = *d2;
+ int result;
+
+ result = strcmp(vr1->ifp->name, vr2->ifp->name);
+ result += !result * (vr1->vrid - vr2->vrid);
+
+ return result;
+}
+
/* clang-format off */
DEFPY(vrrp_vrid_show,
struct list *ll = hash_to_list(vrrp_vrouters_hash);
struct json_object *j = json_object_new_array();
+ list_sort(ll, vrrp_instance_display_sort_cmp);
+
for (ALL_LIST_ELEMENTS_RO(ll, ln, vr)) {
if (ifn && !strmatch(ifn, vr->ifp->name))
continue;
- if (vrid && vrid != vr->vrid)
+ if (vrid && ((uint8_t) vrid) != vr->vrid)
continue;
if (!json)
return CMD_SUCCESS;
}
+DEFPY(vrrp_vrid_show_summary,
+ vrrp_vrid_show_summary_cmd,
+ "show vrrp [interface INTERFACE$ifn] [(1-255)$vrid] summary",
+ SHOW_STR
+ VRRP_STR
+ INTERFACE_STR
+ "Only show VRRP instances on this interface\n"
+ VRRP_VRID_STR
+ "Summarize all VRRP instances\n")
+{
+ struct vrrp_vrouter *vr;
+ struct listnode *ln;
+ struct list *ll = hash_to_list(vrrp_vrouters_hash);
+
+ list_sort(ll, vrrp_instance_display_sort_cmp);
+
+ struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+
+ ttable_add_row(
+ tt, "Interface|VRID|Priority|IPv4|IPv6|State (v4)|State (v6)");
+ ttable_rowseps(tt, 0, BOTTOM, true, '-');
+
+ for (ALL_LIST_ELEMENTS_RO(ll, ln, vr)) {
+ if (ifn && !strmatch(ifn, vr->ifp->name))
+ continue;
+ if (vrid && ((uint8_t)vrid) != vr->vrid)
+ continue;
+
+ ttable_add_row(
+ tt, "%s|%" PRIu8 "|%" PRIu8 "|%d|%d|%s|%s",
+ vr->ifp->name, vr->vrid, vr->priority,
+ vr->v4->addrs->count, vr->v6->addrs->count,
+ vr->v4->fsm.state == VRRP_STATE_MASTER ? "Master"
+ : "Backup",
+ vr->v6->fsm.state == VRRP_STATE_MASTER ? "Master"
+ : "Backup");
+ }
+
+ char *table = ttable_dump(tt, "\n");
+
+ vty_out(vty, "\n%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+
+ list_delete(&ll);
+
+ return CMD_SUCCESS;
+}
+
DEFPY(debug_vrrp,
debug_vrrp_cmd,
if_cmd_init();
install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
+ install_element(VIEW_NODE, &vrrp_vrid_show_summary_cmd);
install_element(VIEW_NODE, &show_debugging_vrrp_cmd);
install_element(VIEW_NODE, &debug_vrrp_cmd);
install_element(CONFIG_NODE, &debug_vrrp_cmd);