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