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