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