3 * Copyright (C) 2018-2019 Cumulus Networks, Inc.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "lib/command.h"
24 #include "lib/ipaddr.h"
26 #include "lib/northbound_cli.h"
27 #include "lib/prefix.h"
28 #include "lib/termtable.h"
33 #include "vrrp_debug.h"
35 #include "vrrp_zebra.h"
36 #ifndef VTYSH_EXTRACT_PL
37 #include "vrrpd/vrrp_vty_clippy.c"
41 #define VRRP_STR "Virtual Router Redundancy Protocol\n"
42 #define VRRP_VRID_STR "Virtual Router ID\n"
43 #define VRRP_PRIORITY_STR "Virtual Router Priority\n"
44 #define VRRP_ADVINT_STR "Virtual Router Advertisement Interval\n"
45 #define VRRP_IP_STR "Virtual Router IP address\n"
46 #define VRRP_VERSION_STR "VRRP protocol version\n"
48 #define VRRP_XPATH_ENTRY VRRP_XPATH "[virtual-router-id='%ld']"
50 /* clang-format off */
53 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group
57 "[no] vrrp (1-255)$vrid [version (2-3)]",
66 snprintf(valbuf
, sizeof(valbuf
), "%ld", version
? version
: vd
.version
);
69 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
71 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
72 nb_cli_enqueue_change(vty
, "./version", NB_OP_MODIFY
, valbuf
);
75 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
78 void cli_show_vrrp(struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
80 const char *vrid
= yang_dnode_get_string(dnode
, "./virtual-router-id");
81 const char *ver
= yang_dnode_get_string(dnode
, "./version");
83 vty_out(vty
, " vrrp %s", vrid
);
84 if (show_defaults
|| !yang_dnode_is_default(dnode
, "./version"))
85 vty_out(vty
, " version %s", ver
);
90 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/shutdown
94 "[no] vrrp (1-255)$vrid shutdown",
98 "Force VRRP router into administrative shutdown\n")
100 nb_cli_enqueue_change(vty
, "./shutdown", NB_OP_MODIFY
,
101 no
? "false" : "true");
103 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
106 void cli_show_shutdown(struct vty
*vty
, struct lyd_node
*dnode
,
109 const char *vrid
= yang_dnode_get_string(dnode
, "../virtual-router-id");
110 const bool shut
= yang_dnode_get_bool(dnode
, NULL
);
112 vty_out(vty
, " %svrrp %s shutdown\n", shut
? "" : "no ", vrid
);
116 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/priority
120 "vrrp (1-255)$vrid priority (1-254)",
126 nb_cli_enqueue_change(vty
, "./priority", NB_OP_MODIFY
, priority_str
);
128 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
132 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/priority
134 DEFPY(no_vrrp_priority
,
135 no_vrrp_priority_cmd
,
136 "no vrrp (1-255)$vrid priority [(1-254)]",
143 nb_cli_enqueue_change(vty
, "./priority", NB_OP_MODIFY
, NULL
);
145 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
148 void cli_show_priority(struct vty
*vty
, struct lyd_node
*dnode
,
151 const char *vrid
= yang_dnode_get_string(dnode
, "../virtual-router-id");
152 const char *prio
= yang_dnode_get_string(dnode
, NULL
);
154 vty_out(vty
, " vrrp %s priority %s\n", vrid
, prio
);
159 * /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/advertisement-interval
161 DEFPY(vrrp_advertisement_interval
,
162 vrrp_advertisement_interval_cmd
,
163 "vrrp (1-255)$vrid advertisement-interval (10-40950)",
164 VRRP_STR VRRP_VRID_STR VRRP_ADVINT_STR
165 "Advertisement interval in milliseconds; must be multiple of 10")
169 /* all internal computations are in centiseconds */
170 advertisement_interval
/= CS2MS
;
171 snprintf(val
, sizeof(val
), "%ld", advertisement_interval
);
172 nb_cli_enqueue_change(vty
, "./advertisement-interval", NB_OP_MODIFY
,
175 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
180 * /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/advertisement-interval
182 DEFPY(no_vrrp_advertisement_interval
,
183 no_vrrp_advertisement_interval_cmd
,
184 "no vrrp (1-255)$vrid advertisement-interval [(10-40950)]",
185 NO_STR VRRP_STR VRRP_VRID_STR VRRP_ADVINT_STR
186 "Advertisement interval in milliseconds; must be multiple of 10")
188 nb_cli_enqueue_change(vty
, "./advertisement-interval", NB_OP_MODIFY
,
191 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
194 void cli_show_advertisement_interval(struct vty
*vty
, struct lyd_node
*dnode
,
197 const char *vrid
= yang_dnode_get_string(dnode
, "../virtual-router-id");
198 uint16_t advint
= yang_dnode_get_uint16(dnode
, NULL
);
200 vty_out(vty
, " vrrp %s advertisement-interval %u\n", vrid
,
206 * /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/v4/virtual-address
210 "[no] vrrp (1-255)$vrid ip A.B.C.D",
217 int op
= no
? NB_OP_DESTROY
: NB_OP_CREATE
;
218 nb_cli_enqueue_change(vty
, "./v4/virtual-address", op
, ip_str
);
220 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
223 void cli_show_ip(struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
226 yang_dnode_get_string(dnode
, "../../virtual-router-id");
227 const char *ipv4
= yang_dnode_get_string(dnode
, NULL
);
229 vty_out(vty
, " vrrp %s ip %s\n", vrid
, ipv4
);
234 * /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/v6/virtual-address
238 "[no] vrrp (1-255)$vrid ipv6 X:X::X:X",
245 int op
= no
? NB_OP_DESTROY
: NB_OP_CREATE
;
246 nb_cli_enqueue_change(vty
, "./v6/virtual-address", op
, ipv6_str
);
248 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
251 void cli_show_ipv6(struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
254 yang_dnode_get_string(dnode
, "../../virtual-router-id");
255 const char *ipv6
= yang_dnode_get_string(dnode
, NULL
);
257 vty_out(vty
, " vrrp %s ipv6 %s\n", vrid
, ipv6
);
261 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/preempt
265 "[no] vrrp (1-255)$vrid preempt",
271 nb_cli_enqueue_change(vty
, "./preempt", NB_OP_MODIFY
,
272 no
? "false" : "true");
274 return nb_cli_apply_changes(vty
, VRRP_XPATH_ENTRY
, vrid
);
277 void cli_show_preempt(struct vty
*vty
, struct lyd_node
*dnode
,
280 const char *vrid
= yang_dnode_get_string(dnode
, "../virtual-router-id");
281 const bool pre
= yang_dnode_get_bool(dnode
, NULL
);
283 vty_out(vty
, " %svrrp %s preempt\n", pre
? "" : "no ", vrid
);
286 /* XXX: yang conversion */
287 DEFPY(vrrp_autoconfigure
,
288 vrrp_autoconfigure_cmd
,
289 "[no] vrrp autoconfigure [version (2-3)]",
292 "Automatically set up VRRP instances on VRRP-compatible interfaces\n"
293 "Version for automatically configured instances\n"
296 version
= version
? version
: 3;
299 vrrp_autoconfig_on(version
);
301 vrrp_autoconfig_off();
306 /* XXX: yang conversion */
309 "[no] vrrp default <advertisement-interval$adv (10-40950)$advint|preempt$p|priority$prio (1-254)$prioval|shutdown$s>",
312 "Configure defaults for new VRRP instances\n"
314 "Advertisement interval in milliseconds\n"
318 "Force VRRP router into administrative shutdown\n")
321 if (advint
% CS2MS
!= 0) {
322 vty_out(vty
, "%% Value must be a multiple of %u\n",
323 (unsigned int)CS2MS
);
324 return CMD_WARNING_CONFIG_FAILED
;
326 /* all internal computations are in centiseconds */
328 vd
.advertisement_interval
= no
? VRRP_DEFAULT_ADVINT
: advint
;
331 vd
.preempt_mode
= !no
;
333 vd
.priority
= no
? VRRP_DEFAULT_PRIORITY
: prioval
;
340 /* clang-format on */
343 * Build JSON representation of VRRP instance.
346 * VRRP router to build json object from
349 * JSON representation of VRRP instance. Must be freed by caller.
351 static struct json_object
*vrrp_build_json(struct vrrp_vrouter
*vr
)
353 char ethstr4
[ETHER_ADDR_STRLEN
];
354 char ethstr6
[ETHER_ADDR_STRLEN
];
355 char ipstr
[INET6_ADDRSTRLEN
];
356 const char *stastr4
= vrrp_state_names
[vr
->v4
->fsm
.state
];
357 const char *stastr6
= vrrp_state_names
[vr
->v6
->fsm
.state
];
358 char sipstr4
[INET6_ADDRSTRLEN
] = {};
359 char sipstr6
[INET6_ADDRSTRLEN
] = {};
362 struct json_object
*j
= json_object_new_object();
363 struct json_object
*v4
= json_object_new_object();
364 struct json_object
*v4_stats
= json_object_new_object();
365 struct json_object
*v4_addrs
= json_object_new_array();
366 struct json_object
*v6
= json_object_new_object();
367 struct json_object
*v6_stats
= json_object_new_object();
368 struct json_object
*v6_addrs
= json_object_new_array();
370 prefix_mac2str(&vr
->v4
->vmac
, ethstr4
, sizeof(ethstr4
));
371 prefix_mac2str(&vr
->v6
->vmac
, ethstr6
, sizeof(ethstr6
));
373 json_object_int_add(j
, "vrid", vr
->vrid
);
374 json_object_int_add(j
, "version", vr
->version
);
375 json_object_boolean_add(j
, "autoconfigured", vr
->autoconf
);
376 json_object_boolean_add(j
, "shutdown", vr
->shutdown
);
377 json_object_boolean_add(j
, "preemptMode", vr
->preempt_mode
);
378 json_object_boolean_add(j
, "acceptMode", vr
->accept_mode
);
379 json_object_string_add(j
, "interface", vr
->ifp
->name
);
380 json_object_int_add(j
, "advertisementInterval",
381 vr
->advertisement_interval
* CS2MS
);
383 json_object_string_add(v4
, "interface",
384 vr
->v4
->mvl_ifp
? vr
->v4
->mvl_ifp
->name
: "");
385 json_object_string_add(v4
, "vmac", ethstr4
);
386 ipaddr2str(&vr
->v4
->src
, sipstr4
, sizeof(sipstr4
));
387 json_object_string_add(v4
, "primaryAddress", sipstr4
);
388 json_object_string_add(v4
, "status", stastr4
);
389 json_object_int_add(v4
, "effectivePriority", vr
->v4
->priority
);
390 json_object_int_add(v4
, "masterAdverInterval",
391 vr
->v4
->master_adver_interval
* CS2MS
);
392 json_object_int_add(v4
, "skewTime", vr
->v4
->skew_time
* CS2MS
);
393 json_object_int_add(v4
, "masterDownInterval",
394 vr
->v4
->master_down_interval
* CS2MS
);
396 json_object_int_add(v4_stats
, "adverTx", vr
->v4
->stats
.adver_tx_cnt
);
397 json_object_int_add(v4_stats
, "adverRx", vr
->v4
->stats
.adver_rx_cnt
);
398 json_object_int_add(v4_stats
, "garpTx", vr
->v4
->stats
.garp_tx_cnt
);
399 json_object_int_add(v4_stats
, "transitions", vr
->v4
->stats
.trans_cnt
);
400 json_object_object_add(v4
, "stats", v4_stats
);
402 if (vr
->v4
->addrs
->count
) {
403 for (ALL_LIST_ELEMENTS_RO(vr
->v4
->addrs
, ln
, ip
)) {
404 inet_ntop(vr
->v4
->family
, &ip
->ipaddr_v4
, ipstr
,
406 json_object_array_add(v4_addrs
,
407 json_object_new_string(ipstr
));
410 json_object_object_add(v4
, "addresses", v4_addrs
);
411 json_object_object_add(j
, "v4", v4
);
414 json_object_string_add(v6
, "interface",
415 vr
->v6
->mvl_ifp
? vr
->v6
->mvl_ifp
->name
: "");
416 json_object_string_add(v6
, "vmac", ethstr6
);
417 ipaddr2str(&vr
->v6
->src
, sipstr6
, sizeof(sipstr6
));
418 if (strlen(sipstr6
) == 0 && vr
->v6
->src
.ip
.addr
== 0x00)
419 strlcat(sipstr6
, "::", sizeof(sipstr6
));
420 json_object_string_add(v6
, "primaryAddress", sipstr6
);
421 json_object_string_add(v6
, "status", stastr6
);
422 json_object_int_add(v6
, "effectivePriority", vr
->v6
->priority
);
423 json_object_int_add(v6
, "masterAdverInterval",
424 vr
->v6
->master_adver_interval
* CS2MS
);
425 json_object_int_add(v6
, "skewTime", vr
->v6
->skew_time
* CS2MS
);
426 json_object_int_add(v6
, "masterDownInterval",
427 vr
->v6
->master_down_interval
* CS2MS
);
429 json_object_int_add(v6_stats
, "adverTx", vr
->v6
->stats
.adver_tx_cnt
);
430 json_object_int_add(v6_stats
, "adverRx", vr
->v6
->stats
.adver_rx_cnt
);
431 json_object_int_add(v6_stats
, "neighborAdverTx",
432 vr
->v6
->stats
.una_tx_cnt
);
433 json_object_int_add(v6_stats
, "transitions", vr
->v6
->stats
.trans_cnt
);
434 json_object_object_add(v6
, "stats", v6_stats
);
436 if (vr
->v6
->addrs
->count
) {
437 for (ALL_LIST_ELEMENTS_RO(vr
->v6
->addrs
, ln
, ip
)) {
438 inet_ntop(vr
->v6
->family
, &ip
->ipaddr_v6
, ipstr
,
440 json_object_array_add(v6_addrs
,
441 json_object_new_string(ipstr
));
444 json_object_object_add(v6
, "addresses", v6_addrs
);
445 json_object_object_add(j
, "v6", v6
);
451 * Dump VRRP instance status to VTY.
457 * VRRP router to dump
459 static void vrrp_show(struct vty
*vty
, struct vrrp_vrouter
*vr
)
461 char ethstr4
[ETHER_ADDR_STRLEN
];
462 char ethstr6
[ETHER_ADDR_STRLEN
];
463 char ipstr
[INET6_ADDRSTRLEN
];
464 const char *stastr4
= vrrp_state_names
[vr
->v4
->fsm
.state
];
465 const char *stastr6
= vrrp_state_names
[vr
->v6
->fsm
.state
];
466 char sipstr4
[INET6_ADDRSTRLEN
] = {};
467 char sipstr6
[INET6_ADDRSTRLEN
] = {};
471 struct ttable
*tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
473 ttable_add_row(tt
, "%s|%" PRIu32
, "Virtual Router ID", vr
->vrid
);
474 ttable_add_row(tt
, "%s|%" PRIu8
, "Protocol Version", vr
->version
);
475 ttable_add_row(tt
, "%s|%s", "Autoconfigured",
476 vr
->autoconf
? "Yes" : "No");
477 ttable_add_row(tt
, "%s|%s", "Shutdown", vr
->shutdown
? "Yes" : "No");
478 ttable_add_row(tt
, "%s|%s", "Interface", vr
->ifp
->name
);
479 prefix_mac2str(&vr
->v4
->vmac
, ethstr4
, sizeof(ethstr4
));
480 prefix_mac2str(&vr
->v6
->vmac
, ethstr6
, sizeof(ethstr6
));
481 ttable_add_row(tt
, "%s|%s", "VRRP interface (v4)",
482 vr
->v4
->mvl_ifp
? vr
->v4
->mvl_ifp
->name
: "None");
483 ttable_add_row(tt
, "%s|%s", "VRRP interface (v6)",
484 vr
->v6
->mvl_ifp
? vr
->v6
->mvl_ifp
->name
: "None");
485 ipaddr2str(&vr
->v4
->src
, sipstr4
, sizeof(sipstr4
));
486 ipaddr2str(&vr
->v6
->src
, sipstr6
, sizeof(sipstr6
));
487 if (strlen(sipstr6
) == 0 && vr
->v6
->src
.ip
.addr
== 0x00)
488 strlcat(sipstr6
, "::", sizeof(sipstr6
));
489 ttable_add_row(tt
, "%s|%s", "Primary IP (v4)", sipstr4
);
490 ttable_add_row(tt
, "%s|%s", "Primary IP (v6)", sipstr6
);
491 ttable_add_row(tt
, "%s|%s", "Virtual MAC (v4)", ethstr4
);
492 ttable_add_row(tt
, "%s|%s", "Virtual MAC (v6)", ethstr6
);
493 ttable_add_row(tt
, "%s|%s", "Status (v4)", stastr4
);
494 ttable_add_row(tt
, "%s|%s", "Status (v6)", stastr6
);
495 ttable_add_row(tt
, "%s|%" PRIu8
, "Priority", vr
->priority
);
496 ttable_add_row(tt
, "%s|%" PRIu8
, "Effective Priority (v4)",
498 ttable_add_row(tt
, "%s|%" PRIu8
, "Effective Priority (v6)",
500 ttable_add_row(tt
, "%s|%s", "Preempt Mode",
501 vr
->preempt_mode
? "Yes" : "No");
502 ttable_add_row(tt
, "%s|%s", "Accept Mode",
503 vr
->accept_mode
? "Yes" : "No");
504 ttable_add_row(tt
, "%s|%d ms", "Advertisement Interval",
505 vr
->advertisement_interval
* CS2MS
);
506 ttable_add_row(tt
, "%s|%d ms",
507 "Master Advertisement Interval (v4)",
508 vr
->v4
->master_adver_interval
* CS2MS
);
509 ttable_add_row(tt
, "%s|%d ms",
510 "Master Advertisement Interval (v6)",
511 vr
->v6
->master_adver_interval
* CS2MS
);
512 ttable_add_row(tt
, "%s|%" PRIu32
, "Advertisements Tx (v4)",
513 vr
->v4
->stats
.adver_tx_cnt
);
514 ttable_add_row(tt
, "%s|%" PRIu32
, "Advertisements Tx (v6)",
515 vr
->v6
->stats
.adver_tx_cnt
);
516 ttable_add_row(tt
, "%s|%" PRIu32
, "Advertisements Rx (v4)",
517 vr
->v4
->stats
.adver_rx_cnt
);
518 ttable_add_row(tt
, "%s|%" PRIu32
, "Advertisements Rx (v6)",
519 vr
->v6
->stats
.adver_rx_cnt
);
520 ttable_add_row(tt
, "%s|%" PRIu32
, "Gratuitous ARP Tx (v4)",
521 vr
->v4
->stats
.garp_tx_cnt
);
522 ttable_add_row(tt
, "%s|%" PRIu32
, "Neigh. Adverts Tx (v6)",
523 vr
->v6
->stats
.una_tx_cnt
);
524 ttable_add_row(tt
, "%s|%" PRIu32
, "State transitions (v4)",
525 vr
->v4
->stats
.trans_cnt
);
526 ttable_add_row(tt
, "%s|%" PRIu32
, "State transitions (v6)",
527 vr
->v6
->stats
.trans_cnt
);
528 ttable_add_row(tt
, "%s|%d ms", "Skew Time (v4)",
529 vr
->v4
->skew_time
* CS2MS
);
530 ttable_add_row(tt
, "%s|%d ms", "Skew Time (v6)",
531 vr
->v6
->skew_time
* CS2MS
);
532 ttable_add_row(tt
, "%s|%d ms", "Master Down Interval (v4)",
533 vr
->v4
->master_down_interval
* CS2MS
);
534 ttable_add_row(tt
, "%s|%d ms", "Master Down Interval (v6)",
535 vr
->v6
->master_down_interval
* CS2MS
);
536 ttable_add_row(tt
, "%s|%u", "IPv4 Addresses", vr
->v4
->addrs
->count
);
540 memset(fill
, '.', sizeof(fill
));
541 fill
[sizeof(fill
) - 1] = 0x00;
542 if (vr
->v4
->addrs
->count
) {
543 for (ALL_LIST_ELEMENTS_RO(vr
->v4
->addrs
, ln
, ip
)) {
544 inet_ntop(vr
->v4
->family
, &ip
->ipaddr_v4
, ipstr
,
546 ttable_add_row(tt
, "%s|%s", fill
, ipstr
);
550 ttable_add_row(tt
, "%s|%u", "IPv6 Addresses", vr
->v6
->addrs
->count
);
552 if (vr
->v6
->addrs
->count
) {
553 for (ALL_LIST_ELEMENTS_RO(vr
->v6
->addrs
, ln
, ip
)) {
554 inet_ntop(vr
->v6
->family
, &ip
->ipaddr_v6
, ipstr
,
556 ttable_add_row(tt
, "%s|%s", fill
, ipstr
);
560 char *table
= ttable_dump(tt
, "\n");
562 vty_out(vty
, "\n%s\n", table
);
563 XFREE(MTYPE_TMP
, table
);
568 * Sort comparator, used when sorting VRRP instances for display purposes.
570 * Sorts by interface name first, then by VRID ascending.
572 static int vrrp_instance_display_sort_cmp(const void **d1
, const void **d2
)
574 const struct vrrp_vrouter
*vr1
= *d1
;
575 const struct vrrp_vrouter
*vr2
= *d2
;
578 result
= strcmp(vr1
->ifp
->name
, vr2
->ifp
->name
);
579 result
+= !result
* (vr1
->vrid
- vr2
->vrid
);
584 /* clang-format off */
586 DEFPY(vrrp_vrid_show
,
588 "show vrrp [interface INTERFACE$ifn] [(1-255)$vrid] [json$json]",
592 "Only show VRRP instances on this interface\n"
596 struct vrrp_vrouter
*vr
;
598 struct list
*ll
= hash_to_list(vrrp_vrouters_hash
);
599 struct json_object
*j
= json_object_new_array();
601 list_sort(ll
, vrrp_instance_display_sort_cmp
);
603 for (ALL_LIST_ELEMENTS_RO(ll
, ln
, vr
)) {
604 if (ifn
&& !strmatch(ifn
, vr
->ifp
->name
))
606 if (vrid
&& ((uint8_t) vrid
) != vr
->vrid
)
612 json_object_array_add(j
, vrrp_build_json(vr
));
617 json_object_to_json_string_ext(
618 j
, JSON_C_TO_STRING_PRETTY
));
627 DEFPY(vrrp_vrid_show_summary
,
628 vrrp_vrid_show_summary_cmd
,
629 "show vrrp [interface INTERFACE$ifn] [(1-255)$vrid] summary",
633 "Only show VRRP instances on this interface\n"
635 "Summarize all VRRP instances\n")
637 struct vrrp_vrouter
*vr
;
639 struct list
*ll
= hash_to_list(vrrp_vrouters_hash
);
641 list_sort(ll
, vrrp_instance_display_sort_cmp
);
643 struct ttable
*tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
646 tt
, "Interface|VRID|Priority|IPv4|IPv6|State (v4)|State (v6)");
647 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
649 for (ALL_LIST_ELEMENTS_RO(ll
, ln
, vr
)) {
650 if (ifn
&& !strmatch(ifn
, vr
->ifp
->name
))
652 if (vrid
&& ((uint8_t)vrid
) != vr
->vrid
)
656 tt
, "%s|%" PRIu8
"|%" PRIu8
"|%d|%d|%s|%s",
657 vr
->ifp
->name
, vr
->vrid
, vr
->priority
,
658 vr
->v4
->addrs
->count
, vr
->v6
->addrs
->count
,
659 vr
->v4
->fsm
.state
== VRRP_STATE_MASTER
? "Master"
661 vr
->v6
->fsm
.state
== VRRP_STATE_MASTER
? "Master"
665 char *table
= ttable_dump(tt
, "\n");
667 vty_out(vty
, "\n%s\n", table
);
668 XFREE(MTYPE_TMP
, table
);
679 "[no] debug vrrp [{protocol$proto|autoconfigure$ac|packets$pkt|sockets$sock|ndisc$ndisc|arp$arp|zebra$zebra}]",
683 "Debug protocol state\n"
684 "Debug autoconfiguration\n"
685 "Debug sent and received packets\n"
686 "Debug socket creation and configuration\n"
687 "Debug Neighbor Discovery\n"
689 "Debug Zebra events\n")
691 /* If no specific are given on/off them all */
692 if (strmatch(argv
[argc
- 1]->text
, "vrrp"))
693 vrrp_debug_set(NULL
, 0, vty
->node
, !no
, true, true, true, true,
696 vrrp_debug_set(NULL
, 0, vty
->node
, !no
, !!proto
, !!ac
, !!pkt
,
697 !!sock
, !!ndisc
, !!arp
, !!zebra
);
702 DEFUN_NOSH (show_debugging_vrrp
,
703 show_debugging_vrrp_cmd
,
704 "show debugging [vrrp]",
707 "VRRP information\n")
709 vty_out(vty
, "VRRP debugging status:\n");
711 vrrp_debug_status_write(vty
);
716 /* clang-format on */
719 * Write per interface VRRP config.
721 static int vrrp_config_write_interface(struct vty
*vty
)
726 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
727 struct interface
*ifp
;
729 FOR_ALL_INTERFACES (vrf
, ifp
) {
730 struct lyd_node
*dnode
;
732 dnode
= yang_dnode_get(
733 running_config
->dnode
,
734 "/frr-interface:lib/interface[name='%s'][vrf='%s']",
735 ifp
->name
, vrf
->name
);
740 nb_cli_show_dnode_cmds(vty
, dnode
, false);
747 static struct cmd_node interface_node
= {INTERFACE_NODE
, "%s(config-if)# ", 1};
748 static struct cmd_node debug_node
= {DEBUG_NODE
, "", 1};
749 static struct cmd_node vrrp_node
= {VRRP_NODE
, "", 1};
751 void vrrp_vty_init(void)
753 install_node(&debug_node
, vrrp_config_write_debug
);
754 install_node(&interface_node
, vrrp_config_write_interface
);
755 install_node(&vrrp_node
, vrrp_config_write_global
);
758 install_element(VIEW_NODE
, &vrrp_vrid_show_cmd
);
759 install_element(VIEW_NODE
, &vrrp_vrid_show_summary_cmd
);
760 install_element(VIEW_NODE
, &show_debugging_vrrp_cmd
);
761 install_element(VIEW_NODE
, &debug_vrrp_cmd
);
762 install_element(CONFIG_NODE
, &debug_vrrp_cmd
);
763 install_element(CONFIG_NODE
, &vrrp_autoconfigure_cmd
);
764 install_element(CONFIG_NODE
, &vrrp_default_cmd
);
765 install_element(INTERFACE_NODE
, &vrrp_vrid_cmd
);
766 install_element(INTERFACE_NODE
, &vrrp_shutdown_cmd
);
767 install_element(INTERFACE_NODE
, &vrrp_priority_cmd
);
768 install_element(INTERFACE_NODE
, &no_vrrp_priority_cmd
);
769 install_element(INTERFACE_NODE
, &vrrp_advertisement_interval_cmd
);
770 install_element(INTERFACE_NODE
, &no_vrrp_advertisement_interval_cmd
);
771 install_element(INTERFACE_NODE
, &vrrp_ip_cmd
);
772 install_element(INTERFACE_NODE
, &vrrp_ip6_cmd
);
773 install_element(INTERFACE_NODE
, &vrrp_preempt_cmd
);