]> git.proxmox.com Git - mirror_frr.git/blame - vrrpd/vrrp_vty.c
lib: add ipaddr_isset()
[mirror_frr.git] / vrrpd / vrrp_vty.c
CommitLineData
5435a2bf 1/*
63d4bd12
QY
2 * VRRP CLI commands.
3 * Copyright (C) 2018-2019 Cumulus Networks, Inc.
4 * Quentin Young
5435a2bf
QY
5 *
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)
9 * any later version.
10 *
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
14 * more details.
15 *
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
19 */
20#include <zebra.h>
21
862f2f37
QY
22#include "lib/command.h"
23#include "lib/if.h"
24#include "lib/ipaddr.h"
6e21b5ae 25#include "lib/json.h"
f495425b 26#include "lib/northbound_cli.h"
862f2f37
QY
27#include "lib/prefix.h"
28#include "lib/termtable.h"
29#include "lib/vty.h"
5435a2bf
QY
30
31#include "vrrp.h"
78fb3dbe 32#include "vrrp_debug.h"
78fb3dbe 33#include "vrrp_vty.h"
138c5a74 34#include "vrrp_zebra.h"
c23edd74
QY
35#ifndef VTYSH_EXTRACT_PL
36#include "vrrpd/vrrp_vty_clippy.c"
37#endif
5435a2bf
QY
38
39
40#define VRRP_STR "Virtual Router Redundancy Protocol\n"
41#define VRRP_VRID_STR "Virtual Router ID\n"
c23edd74 42#define VRRP_PRIORITY_STR "Virtual Router Priority\n"
6287cefe 43#define VRRP_ADVINT_STR "Virtual Router Advertisement Interval\n"
c23edd74 44#define VRRP_IP_STR "Virtual Router IPv4 address\n"
99966840 45#define VRRP_VERSION_STR "VRRP protocol version\n"
c23edd74 46
4f0b6b45 47#define VROUTER_GET_VTY(_vty, _ifp, _vrid, _vr) \
c23edd74 48 do { \
4f0b6b45 49 _vr = vrrp_lookup(_ifp, _vrid); \
c23edd74
QY
50 if (!_vr) { \
51 vty_out(_vty, \
52 "%% Please configure VRRP instance %u\n", \
53 (unsigned int)_vrid); \
54 return CMD_WARNING_CONFIG_FAILED; \
55 } \
2fff50ec 56 } while (0)
5435a2bf 57
f495425b
QY
58#define VRRP_XPATH_ENTRY VRRP_XPATH "[virtual-router-id='%ld']"
59
b637bcd4
QY
60/* clang-format off */
61
f495425b
QY
62/*
63 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group
64 */
c23edd74 65DEFPY(vrrp_vrid,
5435a2bf 66 vrrp_vrid_cmd,
99966840 67 "[no] vrrp (1-255)$vrid [version (2-3)]",
5435a2bf
QY
68 NO_STR
69 VRRP_STR
99966840
QY
70 VRRP_VRID_STR
71 VRRP_VERSION_STR
72 VRRP_VERSION_STR)
5435a2bf 73{
f495425b
QY
74 char valbuf[8];
75
76 snprintf(valbuf, sizeof(valbuf), "%ld", version ? version : vd.version);
5435a2bf 77
f495425b
QY
78 if (no)
79 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
80 else {
81 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
82 nb_cli_enqueue_change(vty, "./version", NB_OP_MODIFY, valbuf);
83 }
6287cefe 84
f495425b
QY
85 return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
86}
99966840 87
f495425b
QY
88void cli_show_vrrp(struct vty *vty, struct lyd_node *dnode, bool show_defaults)
89{
90 const char *vrid = yang_dnode_get_string(dnode, "./virtual-router-id");
91 const char *ver = yang_dnode_get_string(dnode, "./version");
92 const char *dver =
93 yang_get_default_string("%s/version", VRRP_XPATH_FULL);
5435a2bf 94
f495425b
QY
95 char verstr[16] = {};
96
97 if (strmatch(dver, ver)) {
98 if (show_defaults)
99 snprintf(verstr, sizeof(verstr), "version %s", dver);
100 } else {
101 snprintf(verstr, sizeof(verstr), "version %s", ver);
102 }
103
104 vty_out(vty, " vrrp %s %s\n", vrid, verstr);
5435a2bf
QY
105}
106
f495425b
QY
107/*
108 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/shutdown
109 */
f96a183b
QY
110DEFPY(vrrp_shutdown,
111 vrrp_shutdown_cmd,
112 "[no] vrrp (1-255)$vrid shutdown",
113 NO_STR
114 VRRP_STR
115 VRRP_VRID_STR
116 "Force VRRP router into administrative shutdown\n")
117{
f495425b
QY
118 nb_cli_enqueue_change(vty, "./shutdown", NB_OP_MODIFY,
119 no ? "false" : "true");
f96a183b 120
f495425b
QY
121 return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
122}
f96a183b 123
f495425b
QY
124void cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
125 bool show_defaults)
126{
127 const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
128 const bool shut = yang_dnode_get_bool(dnode, NULL);
f96a183b 129
f495425b 130 vty_out(vty, " %svrrp %s shutdown\n", shut ? "" : "no ", vrid);
f96a183b
QY
131}
132
f495425b
QY
133/*
134 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/priority
135 */
c23edd74
QY
136DEFPY(vrrp_priority,
137 vrrp_priority_cmd,
d7cfcdc0 138 "[no] vrrp (1-255)$vrid priority (1-254)",
c23edd74
QY
139 NO_STR
140 VRRP_STR
141 VRRP_VRID_STR
142 VRRP_PRIORITY_STR
bac08ded 143 "Priority value")
c23edd74 144{
f495425b 145 const char *val = no ? NULL : priority_str;
4f0b6b45 146
f495425b 147 nb_cli_enqueue_change(vty, "./priority", NB_OP_MODIFY, val);
c23edd74 148
f495425b
QY
149 return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
150}
1d21789e 151
f495425b
QY
152void cli_show_priority(struct vty *vty, struct lyd_node *dnode,
153 bool show_defaults)
154{
155 const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
156 const char *prio = yang_dnode_get_string(dnode, NULL);
1d21789e 157
f495425b 158 vty_out(vty, " vrrp %s priority %s\n", vrid, prio);
1d21789e
QY
159}
160
f495425b
QY
161/*
162 * XPath:
163 * /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/advertisement-interval
164 */
1d21789e
QY
165DEFPY(vrrp_advertisement_interval,
166 vrrp_advertisement_interval_cmd,
cb44d476 167 "[no] vrrp (1-255)$vrid advertisement-interval (10-40950)",
6287cefe 168 NO_STR VRRP_STR VRRP_VRID_STR VRRP_ADVINT_STR
cb44d476 169 "Advertisement interval in milliseconds; must be multiple of 10")
1d21789e 170{
f495425b
QY
171 char valbuf[8];
172 const char *val;
4f0b6b45 173
f495425b
QY
174 /* all internal computations are in centiseconds */
175 advertisement_interval /= CS2MS;
176 snprintf(valbuf, sizeof(valbuf), "%ld", advertisement_interval);
1d21789e 177
f495425b 178 val = no ? NULL : valbuf;
cb44d476 179
f495425b
QY
180 nb_cli_enqueue_change(vty, "./advertisement-interval", NB_OP_MODIFY,
181 val);
182
183 return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
184}
cb44d476 185
f495425b
QY
186void cli_show_advertisement_interval(struct vty *vty, struct lyd_node *dnode,
187 bool show_defaults)
188{
189 const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
190 const char *advi = yang_dnode_get_string(dnode, NULL);
c23edd74 191
f495425b 192 vty_out(vty, " vrrp %s advertisement-interval %s\n", vrid, advi);
c23edd74
QY
193}
194
f495425b
QY
195/*
196 * XPath:
197 * /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/v4/virtual-address
198 */
c23edd74
QY
199DEFPY(vrrp_ip,
200 vrrp_ip_cmd,
862f2f37 201 "[no] vrrp (1-255)$vrid ip A.B.C.D",
c23edd74
QY
202 NO_STR
203 VRRP_STR
204 VRRP_VRID_STR
862f2f37 205 "Add IPv4 address\n"
c23edd74
QY
206 VRRP_IP_STR)
207{
f495425b
QY
208 int op = no ? NB_OP_DESTROY : NB_OP_CREATE;
209 nb_cli_enqueue_change(vty, "./v4/virtual-address", op, ip_str);
862f2f37 210
f495425b
QY
211 return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
212}
2cd90902 213
f495425b
QY
214void cli_show_ip(struct vty *vty, struct lyd_node *dnode, bool show_defaults)
215{
216 const char *vrid =
217 yang_dnode_get_string(dnode, "../../virtual-router-id");
218 const char *ipv4 = yang_dnode_get_string(dnode, NULL);
862f2f37 219
f495425b 220 vty_out(vty, " vrrp %s ip %s\n", vrid, ipv4);
862f2f37
QY
221}
222
f495425b
QY
223/*
224 * XPath:
225 * /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/v6/virtual-address
226 */
862f2f37
QY
227DEFPY(vrrp_ip6,
228 vrrp_ip6_cmd,
229 "[no] vrrp (1-255)$vrid ipv6 X:X::X:X",
230 NO_STR
231 VRRP_STR
232 VRRP_VRID_STR
233 "Add IPv6 address\n"
234 VRRP_IP_STR)
235{
f495425b
QY
236 int op = no ? NB_OP_DESTROY : NB_OP_CREATE;
237 nb_cli_enqueue_change(vty, "./v6/virtual-address", op, ipv6_str);
862f2f37 238
f495425b
QY
239 return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
240}
2cd90902 241
f495425b
QY
242void cli_show_ipv6(struct vty *vty, struct lyd_node *dnode, bool show_defaults)
243{
244 const char *vrid =
245 yang_dnode_get_string(dnode, "../../virtual-router-id");
246 const char *ipv6 = yang_dnode_get_string(dnode, NULL);
1d21789e 247
f495425b 248 vty_out(vty, " vrrp %s ipv6 %s\n", vrid, ipv6);
c23edd74
QY
249}
250
f495425b
QY
251/*
252 * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/preempt
253 */
8ec51216
QY
254DEFPY(vrrp_preempt,
255 vrrp_preempt_cmd,
256 "[no] vrrp (1-255)$vrid preempt",
257 NO_STR
258 VRRP_STR
259 VRRP_VRID_STR
260 "Preempt mode\n")
261{
f495425b
QY
262 nb_cli_enqueue_change(vty, "./preempt", NB_OP_MODIFY,
263 no ? "false" : "true");
8ec51216 264
f495425b
QY
265 return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
266}
8ec51216 267
f495425b
QY
268void cli_show_preempt(struct vty *vty, struct lyd_node *dnode,
269 bool show_defaults)
270{
271 const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
272 const bool pre = yang_dnode_get_bool(dnode, NULL);
8ec51216 273
f495425b 274 vty_out(vty, " %svrrp %s preempt\n", pre ? "" : "no ", vrid);
8ec51216
QY
275}
276
f495425b 277/* XXX: yang conversion */
27fd8827
QY
278DEFPY(vrrp_autoconfigure,
279 vrrp_autoconfigure_cmd,
280 "[no] vrrp autoconfigure [version (2-3)]",
53e60e5c
QY
281 NO_STR
282 VRRP_STR
283 "Automatically set up VRRP instances on VRRP-compatible interfaces\n"
284 "Version for automatically configured instances\n"
285 VRRP_VERSION_STR)
286{
53e60e5c
QY
287 version = version ? version : 3;
288
27fd8827
QY
289 if (!no)
290 vrrp_autoconfig_on(version);
291 else
292 vrrp_autoconfig_off();
53e60e5c
QY
293
294 return CMD_SUCCESS;
295}
296
f495425b 297/* XXX: yang conversion */
8cd1d277
QY
298DEFPY(vrrp_default,
299 vrrp_default_cmd,
33b010a9 300 "[no] vrrp default <advertisement-interval$adv (10-40950)$advint|preempt$p|priority$prio (1-254)$prioval|shutdown$s>",
8cd1d277
QY
301 NO_STR
302 VRRP_STR
303 "Configure defaults for new VRRP instances\n"
304 VRRP_ADVINT_STR
33b010a9 305 "Advertisement interval in milliseconds\n"
8cd1d277
QY
306 "Preempt mode\n"
307 VRRP_PRIORITY_STR
308 "Priority value\n"
309 "Force VRRP router into administrative shutdown\n")
310{
33b010a9 311 if (adv) {
de7fe61e
GN
312 if (advint % CS2MS != 0) {
313 vty_out(vty, "%% Value must be a multiple of %u\n",
314 (unsigned int)CS2MS);
33b010a9
QY
315 return CMD_WARNING_CONFIG_FAILED;
316 }
317 /* all internal computations are in centiseconds */
318 advint /= CS2MS;
8cd1d277 319 vd.advertisement_interval = no ? VRRP_DEFAULT_ADVINT : advint;
33b010a9 320 }
8cd1d277
QY
321 if (p)
322 vd.preempt_mode = !no;
323 if (prio)
324 vd.priority = no ? VRRP_DEFAULT_PRIORITY : prioval;
325 if (s)
326 vd.shutdown = !no;
327
328 return CMD_SUCCESS;
329}
330
6332c77f
QY
331/* clang-format on */
332
6e21b5ae
QY
333/*
334 * Build JSON representation of VRRP instance.
335 *
336 * vr
337 * VRRP router to build json object from
338 *
339 * Returns:
340 * JSON representation of VRRP instance. Must be freed by caller.
341 */
342static struct json_object *vrrp_build_json(struct vrrp_vrouter *vr)
343{
344 char ethstr4[ETHER_ADDR_STRLEN];
345 char ethstr6[ETHER_ADDR_STRLEN];
346 char ipstr[INET6_ADDRSTRLEN];
347 const char *stastr4 = vrrp_state_names[vr->v4->fsm.state];
348 const char *stastr6 = vrrp_state_names[vr->v6->fsm.state];
23804b4f
QY
349 char sipstr4[INET6_ADDRSTRLEN] = {};
350 char sipstr6[INET6_ADDRSTRLEN] = {};
6e21b5ae
QY
351 struct listnode *ln;
352 struct ipaddr *ip;
353 struct json_object *j = json_object_new_object();
354 struct json_object *v4 = json_object_new_object();
6332c77f 355 struct json_object *v4_stats = json_object_new_object();
6e21b5ae
QY
356 struct json_object *v4_addrs = json_object_new_array();
357 struct json_object *v6 = json_object_new_object();
6332c77f 358 struct json_object *v6_stats = json_object_new_object();
6e21b5ae
QY
359 struct json_object *v6_addrs = json_object_new_array();
360
361 prefix_mac2str(&vr->v4->vmac, ethstr4, sizeof(ethstr4));
362 prefix_mac2str(&vr->v6->vmac, ethstr6, sizeof(ethstr6));
363
364 json_object_int_add(j, "vrid", vr->vrid);
365 json_object_int_add(j, "version", vr->version);
366 json_object_boolean_add(j, "autoconfigured", vr->autoconf);
367 json_object_boolean_add(j, "shutdown", vr->shutdown);
b1d7f513
QY
368 json_object_boolean_add(j, "preemptMode", vr->preempt_mode);
369 json_object_boolean_add(j, "acceptMode", vr->accept_mode);
6e21b5ae 370 json_object_string_add(j, "interface", vr->ifp->name);
0a7b203e
QY
371 json_object_int_add(j, "advertisementInterval",
372 vr->advertisement_interval * CS2MS);
6e21b5ae
QY
373 /* v4 */
374 json_object_string_add(v4, "interface",
375 vr->v4->mvl_ifp ? vr->v4->mvl_ifp->name : "");
376 json_object_string_add(v4, "vmac", ethstr4);
23804b4f
QY
377 ipaddr2str(&vr->v4->src, sipstr4, sizeof(sipstr4));
378 json_object_string_add(v4, "primaryAddress", sipstr4);
6e21b5ae 379 json_object_string_add(v4, "status", stastr4);
b1d7f513
QY
380 json_object_int_add(v4, "effectivePriority", vr->v4->priority);
381 json_object_int_add(v4, "masterAdverInterval",
cb44d476
QY
382 vr->v4->master_adver_interval * CS2MS);
383 json_object_int_add(v4, "skewTime", vr->v4->skew_time * CS2MS);
b1d7f513 384 json_object_int_add(v4, "masterDownInterval",
cb44d476 385 vr->v4->master_down_interval * CS2MS);
6332c77f
QY
386 /* v4 stats */
387 json_object_int_add(v4_stats, "adverTx", vr->v4->stats.adver_tx_cnt);
388 json_object_int_add(v4_stats, "adverRx", vr->v4->stats.adver_rx_cnt);
389 json_object_int_add(v4_stats, "garpTx", vr->v4->stats.garp_tx_cnt);
390 json_object_int_add(v4_stats, "transitions", vr->v4->stats.trans_cnt);
391 json_object_object_add(v4, "stats", v4_stats);
392 /* v4 addrs */
6e21b5ae
QY
393 if (vr->v4->addrs->count) {
394 for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ln, ip)) {
395 inet_ntop(vr->v4->family, &ip->ipaddr_v4, ipstr,
396 sizeof(ipstr));
397 json_object_array_add(v4_addrs,
398 json_object_new_string(ipstr));
399 }
400 }
401 json_object_object_add(v4, "addresses", v4_addrs);
402 json_object_object_add(j, "v4", v4);
403
404 /* v6 */
405 json_object_string_add(v6, "interface",
406 vr->v6->mvl_ifp ? vr->v6->mvl_ifp->name : "");
407 json_object_string_add(v6, "vmac", ethstr6);
23804b4f
QY
408 ipaddr2str(&vr->v6->src, sipstr6, sizeof(sipstr6));
409 if (strlen(sipstr6) == 0 && vr->v6->src.ip.addr == 0x00)
410 strlcat(sipstr6, "::", sizeof(sipstr6));
411 json_object_string_add(v6, "primaryAddress", sipstr6);
6e21b5ae 412 json_object_string_add(v6, "status", stastr6);
b1d7f513
QY
413 json_object_int_add(v6, "effectivePriority", vr->v6->priority);
414 json_object_int_add(v6, "masterAdverInterval",
cb44d476
QY
415 vr->v6->master_adver_interval * CS2MS);
416 json_object_int_add(v6, "skewTime", vr->v6->skew_time * CS2MS);
b1d7f513 417 json_object_int_add(v6, "masterDownInterval",
cb44d476 418 vr->v6->master_down_interval * CS2MS);
6332c77f
QY
419 /* v6 stats */
420 json_object_int_add(v6_stats, "adverTx", vr->v6->stats.adver_tx_cnt);
421 json_object_int_add(v6_stats, "adverRx", vr->v6->stats.adver_rx_cnt);
422 json_object_int_add(v6_stats, "neighborAdverTx",
423 vr->v6->stats.una_tx_cnt);
424 json_object_int_add(v6_stats, "transitions", vr->v6->stats.trans_cnt);
425 json_object_object_add(v6, "stats", v6_stats);
426 /* v6 addrs */
6e21b5ae
QY
427 if (vr->v6->addrs->count) {
428 for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ln, ip)) {
429 inet_ntop(vr->v6->family, &ip->ipaddr_v6, ipstr,
430 sizeof(ipstr));
431 json_object_array_add(v6_addrs,
432 json_object_new_string(ipstr));
433 }
434 }
435 json_object_object_add(v6, "addresses", v6_addrs);
436 json_object_object_add(j, "v6", v6);
437
438 return j;
439}
440
789ce3af
QY
441/*
442 * Dump VRRP instance status to VTY.
443 *
444 * vty
445 * vty to dump to
446 *
447 * vr
448 * VRRP router to dump
449 */
1d21789e 450static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
c23edd74 451{
862f2f37
QY
452 char ethstr4[ETHER_ADDR_STRLEN];
453 char ethstr6[ETHER_ADDR_STRLEN];
454 char ipstr[INET6_ADDRSTRLEN];
455 const char *stastr4 = vrrp_state_names[vr->v4->fsm.state];
456 const char *stastr6 = vrrp_state_names[vr->v6->fsm.state];
23804b4f
QY
457 char sipstr4[INET6_ADDRSTRLEN] = {};
458 char sipstr6[INET6_ADDRSTRLEN] = {};
862f2f37
QY
459 struct listnode *ln;
460 struct ipaddr *ip;
c23edd74
QY
461
462 struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
463
464 ttable_add_row(tt, "%s|%" PRIu32, "Virtual Router ID", vr->vrid);
99966840 465 ttable_add_row(tt, "%s|%" PRIu8, "Protocol Version", vr->version);
27fd8827
QY
466 ttable_add_row(tt, "%s|%s", "Autoconfigured",
467 vr->autoconf ? "Yes" : "No");
f96a183b 468 ttable_add_row(tt, "%s|%s", "Shutdown", vr->shutdown ? "Yes" : "No");
5302f67b 469 ttable_add_row(tt, "%s|%s", "Interface", vr->ifp->name);
862f2f37
QY
470 prefix_mac2str(&vr->v4->vmac, ethstr4, sizeof(ethstr4));
471 prefix_mac2str(&vr->v6->vmac, ethstr6, sizeof(ethstr6));
5302f67b
QY
472 ttable_add_row(tt, "%s|%s", "VRRP interface (v4)",
473 vr->v4->mvl_ifp ? vr->v4->mvl_ifp->name : "None");
474 ttable_add_row(tt, "%s|%s", "VRRP interface (v6)",
475 vr->v6->mvl_ifp ? vr->v6->mvl_ifp->name : "None");
c7e65c4f
QY
476 ipaddr2str(&vr->v4->src, sipstr4, sizeof(sipstr4));
477 ipaddr2str(&vr->v6->src, sipstr6, sizeof(sipstr6));
23804b4f
QY
478 if (strlen(sipstr6) == 0 && vr->v6->src.ip.addr == 0x00)
479 strlcat(sipstr6, "::", sizeof(sipstr6));
c7e65c4f
QY
480 ttable_add_row(tt, "%s|%s", "Primary IP (v4)", sipstr4);
481 ttable_add_row(tt, "%s|%s", "Primary IP (v6)", sipstr6);
862f2f37
QY
482 ttable_add_row(tt, "%s|%s", "Virtual MAC (v4)", ethstr4);
483 ttable_add_row(tt, "%s|%s", "Virtual MAC (v6)", ethstr6);
484 ttable_add_row(tt, "%s|%s", "Status (v4)", stastr4);
485 ttable_add_row(tt, "%s|%s", "Status (v6)", stastr6);
c23edd74 486 ttable_add_row(tt, "%s|%" PRIu8, "Priority", vr->priority);
862f2f37
QY
487 ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v4)",
488 vr->v4->priority);
489 ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v6)",
490 vr->v6->priority);
c23edd74
QY
491 ttable_add_row(tt, "%s|%s", "Preempt Mode",
492 vr->preempt_mode ? "Yes" : "No");
493 ttable_add_row(tt, "%s|%s", "Accept Mode",
494 vr->accept_mode ? "Yes" : "No");
cb44d476
QY
495 ttable_add_row(tt, "%s|%d ms", "Advertisement Interval",
496 vr->advertisement_interval * CS2MS);
497 ttable_add_row(tt, "%s|%d ms",
789ce3af 498 "Master Advertisement Interval (v4)",
cb44d476
QY
499 vr->v4->master_adver_interval * CS2MS);
500 ttable_add_row(tt, "%s|%d ms",
789ce3af 501 "Master Advertisement Interval (v6)",
cb44d476 502 vr->v6->master_adver_interval * CS2MS);
6332c77f
QY
503 ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Tx (v4)",
504 vr->v4->stats.adver_tx_cnt);
505 ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Tx (v6)",
506 vr->v6->stats.adver_tx_cnt);
507 ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Rx (v4)",
508 vr->v4->stats.adver_rx_cnt);
509 ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Rx (v6)",
510 vr->v6->stats.adver_rx_cnt);
511 ttable_add_row(tt, "%s|%" PRIu32, "Gratuitous ARP Tx (v4)",
512 vr->v4->stats.garp_tx_cnt);
513 ttable_add_row(tt, "%s|%" PRIu32, "Neigh. Adverts Tx (v6)",
514 vr->v6->stats.una_tx_cnt);
515 ttable_add_row(tt, "%s|%" PRIu32, "State transitions (v4)",
516 vr->v4->stats.trans_cnt);
517 ttable_add_row(tt, "%s|%" PRIu32, "State transitions (v6)",
518 vr->v6->stats.trans_cnt);
cb44d476
QY
519 ttable_add_row(tt, "%s|%d ms", "Skew Time (v4)",
520 vr->v4->skew_time * CS2MS);
521 ttable_add_row(tt, "%s|%d ms", "Skew Time (v6)",
522 vr->v6->skew_time * CS2MS);
523 ttable_add_row(tt, "%s|%d ms", "Master Down Interval (v4)",
524 vr->v4->master_down_interval * CS2MS);
525 ttable_add_row(tt, "%s|%d ms", "Master Down Interval (v6)",
526 vr->v6->master_down_interval * CS2MS);
862f2f37 527 ttable_add_row(tt, "%s|%u", "IPv4 Addresses", vr->v4->addrs->count);
c23edd74 528
92c399a4 529 char fill[35];
2fff50ec 530
5302f67b
QY
531 memset(fill, '.', sizeof(fill));
532 fill[sizeof(fill) - 1] = 0x00;
862f2f37 533 if (vr->v4->addrs->count) {
862f2f37
QY
534 for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ln, ip)) {
535 inet_ntop(vr->v4->family, &ip->ipaddr_v4, ipstr,
536 sizeof(ipstr));
5302f67b 537 ttable_add_row(tt, "%s|%s", fill, ipstr);
862f2f37 538 }
862f2f37
QY
539 }
540
5302f67b
QY
541 ttable_add_row(tt, "%s|%u", "IPv6 Addresses", vr->v6->addrs->count);
542
862f2f37 543 if (vr->v6->addrs->count) {
862f2f37
QY
544 for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ln, ip)) {
545 inet_ntop(vr->v6->family, &ip->ipaddr_v6, ipstr,
546 sizeof(ipstr));
5302f67b 547 ttable_add_row(tt, "%s|%s", fill, ipstr);
c23edd74 548 }
c23edd74 549 }
5302f67b
QY
550
551 char *table = ttable_dump(tt, "\n");
2fff50ec 552
5302f67b
QY
553 vty_out(vty, "\n%s\n", table);
554 XFREE(MTYPE_TMP, table);
555 ttable_del(tt);
1d21789e
QY
556}
557
30a1595d
QY
558/*
559 * Sort comparator, used when sorting VRRP instances for display purposes.
560 *
561 * Sorts by interface name first, then by VRID ascending.
562 */
563static int vrrp_instance_display_sort_cmp(const void **d1, const void **d2)
564{
565 const struct vrrp_vrouter *vr1 = *d1;
566 const struct vrrp_vrouter *vr2 = *d2;
567 int result;
568
569 result = strcmp(vr1->ifp->name, vr2->ifp->name);
570 result += !result * (vr1->vrid - vr2->vrid);
571
572 return result;
573}
574
6332c77f
QY
575/* clang-format off */
576
1d21789e
QY
577DEFPY(vrrp_vrid_show,
578 vrrp_vrid_show_cmd,
6e21b5ae 579 "show vrrp [interface INTERFACE$ifn] [(1-255)$vrid] [json$json]",
1d21789e
QY
580 SHOW_STR
581 VRRP_STR
4f0b6b45
QY
582 INTERFACE_STR
583 "Only show VRRP instances on this interface\n"
6e21b5ae
QY
584 VRRP_VRID_STR
585 JSON_STR)
1d21789e
QY
586{
587 struct vrrp_vrouter *vr;
4f0b6b45
QY
588 struct listnode *ln;
589 struct list *ll = hash_to_list(vrrp_vrouters_hash);
6e21b5ae 590 struct json_object *j = json_object_new_array();
1d21789e 591
30a1595d
QY
592 list_sort(ll, vrrp_instance_display_sort_cmp);
593
4f0b6b45
QY
594 for (ALL_LIST_ELEMENTS_RO(ll, ln, vr)) {
595 if (ifn && !strmatch(ifn, vr->ifp->name))
596 continue;
48cd8f13 597 if (vrid && ((uint8_t) vrid) != vr->vrid)
4f0b6b45 598 continue;
5302f67b 599
6e21b5ae
QY
600 if (!json)
601 vrrp_show(vty, vr);
602 else
603 json_object_array_add(j, vrrp_build_json(vr));
1d21789e 604 }
c23edd74 605
6e21b5ae
QY
606 if (json)
607 vty_out(vty, "%s\n",
608 json_object_to_json_string_ext(
609 j, JSON_C_TO_STRING_PRETTY));
610
611 json_object_free(j);
612
4f0b6b45
QY
613 list_delete(&ll);
614
c23edd74
QY
615 return CMD_SUCCESS;
616}
617
30a1595d
QY
618DEFPY(vrrp_vrid_show_summary,
619 vrrp_vrid_show_summary_cmd,
620 "show vrrp [interface INTERFACE$ifn] [(1-255)$vrid] summary",
621 SHOW_STR
622 VRRP_STR
623 INTERFACE_STR
624 "Only show VRRP instances on this interface\n"
625 VRRP_VRID_STR
626 "Summarize all VRRP instances\n")
627{
628 struct vrrp_vrouter *vr;
629 struct listnode *ln;
630 struct list *ll = hash_to_list(vrrp_vrouters_hash);
631
632 list_sort(ll, vrrp_instance_display_sort_cmp);
633
634 struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
635
636 ttable_add_row(
637 tt, "Interface|VRID|Priority|IPv4|IPv6|State (v4)|State (v6)");
638 ttable_rowseps(tt, 0, BOTTOM, true, '-');
639
640 for (ALL_LIST_ELEMENTS_RO(ll, ln, vr)) {
641 if (ifn && !strmatch(ifn, vr->ifp->name))
642 continue;
643 if (vrid && ((uint8_t)vrid) != vr->vrid)
644 continue;
645
646 ttable_add_row(
647 tt, "%s|%" PRIu8 "|%" PRIu8 "|%d|%d|%s|%s",
648 vr->ifp->name, vr->vrid, vr->priority,
649 vr->v4->addrs->count, vr->v6->addrs->count,
650 vr->v4->fsm.state == VRRP_STATE_MASTER ? "Master"
651 : "Backup",
652 vr->v6->fsm.state == VRRP_STATE_MASTER ? "Master"
653 : "Backup");
654 }
655
656 char *table = ttable_dump(tt, "\n");
657
658 vty_out(vty, "\n%s\n", table);
659 XFREE(MTYPE_TMP, table);
660 ttable_del(tt);
661
662 list_delete(&ll);
663
664 return CMD_SUCCESS;
665}
666
78fb3dbe
QY
667
668DEFPY(debug_vrrp,
669 debug_vrrp_cmd,
670 "[no] debug vrrp [{protocol$proto|autoconfigure$ac|packets$pkt|sockets$sock|ndisc$ndisc|arp$arp|zebra$zebra}]",
671 NO_STR
672 DEBUG_STR
673 VRRP_STR
674 "Debug protocol state\n"
675 "Debug autoconfiguration\n"
676 "Debug sent and received packets\n"
677 "Debug socket creation and configuration\n"
678 "Debug Neighbor Discovery\n"
679 "Debug ARP\n"
680 "Debug Zebra events\n")
681{
682 /* If no specific are given on/off them all */
683 if (strmatch(argv[argc - 1]->text, "vrrp"))
684 vrrp_debug_set(NULL, 0, vty->node, !no, true, true, true, true,
685 true, true, true);
686 else
687 vrrp_debug_set(NULL, 0, vty->node, !no, !!proto, !!ac, !!pkt,
688 !!sock, !!ndisc, !!arp, !!zebra);
689
690 return CMD_SUCCESS;
691}
692
693DEFUN_NOSH (show_debugging_vrrp,
694 show_debugging_vrrp_cmd,
695 "show debugging [vrrp]",
696 SHOW_STR
697 DEBUG_STR
698 "VRRP information\n")
699{
700 vty_out(vty, "VRRP debugging status:\n");
701
702 vrrp_debug_status_write(vty);
703
704 return CMD_SUCCESS;
705}
706
b637bcd4
QY
707/* clang-format on */
708
f828842a 709static struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1};
78fb3dbe 710static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
f828842a 711static struct cmd_node vrrp_node = {VRRP_NODE, "", 1};
78fb3dbe 712
5435a2bf
QY
713void vrrp_vty_init(void)
714{
f828842a
QY
715 install_node(&debug_node, vrrp_config_write_debug);
716 install_node(&interface_node, vrrp_config_write_interface);
717 install_node(&vrrp_node, vrrp_config_write_global);
5435a2bf 718 if_cmd_init();
78fb3dbe 719
c23edd74 720 install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
30a1595d 721 install_element(VIEW_NODE, &vrrp_vrid_show_summary_cmd);
78fb3dbe
QY
722 install_element(VIEW_NODE, &show_debugging_vrrp_cmd);
723 install_element(VIEW_NODE, &debug_vrrp_cmd);
724 install_element(CONFIG_NODE, &debug_vrrp_cmd);
27fd8827 725 install_element(CONFIG_NODE, &vrrp_autoconfigure_cmd);
8cd1d277 726 install_element(CONFIG_NODE, &vrrp_default_cmd);
5435a2bf 727 install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
f96a183b 728 install_element(INTERFACE_NODE, &vrrp_shutdown_cmd);
c23edd74 729 install_element(INTERFACE_NODE, &vrrp_priority_cmd);
1d21789e 730 install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd);
c23edd74 731 install_element(INTERFACE_NODE, &vrrp_ip_cmd);
862f2f37 732 install_element(INTERFACE_NODE, &vrrp_ip6_cmd);
8ec51216 733 install_element(INTERFACE_NODE, &vrrp_preempt_cmd);
5435a2bf 734}