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