]> git.proxmox.com Git - mirror_frr.git/blob - vrrpd/vrrp_vty.c
vrrpd: add administrative shutdown option
[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/prefix.h"
26 #include "lib/termtable.h"
27 #include "lib/vty.h"
28
29 #include "vrrp.h"
30 #include "vrrp_debug.h"
31 #include "vrrp_memory.h"
32 #include "vrrp_vty.h"
33 #ifndef VTYSH_EXTRACT_PL
34 #include "vrrpd/vrrp_vty_clippy.c"
35 #endif
36
37
38 #define VRRP_STR "Virtual Router Redundancy Protocol\n"
39 #define VRRP_VRID_STR "Virtual Router ID\n"
40 #define VRRP_PRIORITY_STR "Virtual Router Priority\n"
41 #define VRRP_ADVINT_STR "Virtual Router Advertisement Interval\n"
42 #define VRRP_IP_STR "Virtual Router IPv4 address\n"
43 #define VRRP_VERSION_STR "VRRP protocol version\n"
44
45 #define VROUTER_GET_VTY(_vty, _ifp, _vrid, _vr) \
46 do { \
47 _vr = vrrp_lookup(_ifp, _vrid); \
48 if (!_vr) { \
49 vty_out(_vty, \
50 "%% Please configure VRRP instance %u\n", \
51 (unsigned int)_vrid); \
52 return CMD_WARNING_CONFIG_FAILED; \
53 } \
54 } while (0);
55
56 /* clang-format off */
57
58 DEFPY(vrrp_vrid,
59 vrrp_vrid_cmd,
60 "[no] vrrp (1-255)$vrid [version (2-3)]",
61 NO_STR
62 VRRP_STR
63 VRRP_VRID_STR
64 VRRP_VERSION_STR
65 VRRP_VERSION_STR)
66 {
67 VTY_DECLVAR_CONTEXT(interface, ifp);
68
69 struct vrrp_vrouter *vr = vrrp_lookup(ifp, vrid);
70
71 if (version == 0)
72 version = 3;
73
74 if (no && vr)
75 vrrp_vrouter_destroy(vr);
76 else if (no && !vr)
77 vty_out(vty, "%% VRRP instance %ld does not exist on %s\n",
78 vrid, ifp->name);
79 else if (!vr)
80 vrrp_vrouter_create(ifp, vrid, version);
81 else if (vr)
82 vty_out(vty, "%% VRRP instance %ld already exists on %s\n",
83 vrid, ifp->name);
84
85 return CMD_SUCCESS;
86 }
87
88 DEFPY(vrrp_shutdown,
89 vrrp_shutdown_cmd,
90 "[no] vrrp (1-255)$vrid shutdown",
91 NO_STR
92 VRRP_STR
93 VRRP_VRID_STR
94 "Force VRRP router into administrative shutdown\n")
95 {
96 VTY_DECLVAR_CONTEXT(interface, ifp);
97
98 struct vrrp_vrouter *vr;
99
100 VROUTER_GET_VTY(vty, ifp, vrid, vr);
101
102 if (!no) {
103 if (vr->v4->fsm.state != VRRP_STATE_INITIALIZE)
104 vrrp_event(vr->v4, VRRP_EVENT_SHUTDOWN);
105 if (vr->v6->fsm.state != VRRP_STATE_INITIALIZE)
106 vrrp_event(vr->v6, VRRP_EVENT_SHUTDOWN);
107 vr->shutdown = true;
108 } else {
109 vr->shutdown = false;
110 vrrp_check_start(vr);
111 }
112
113 return CMD_SUCCESS;
114 }
115
116 DEFPY(vrrp_priority,
117 vrrp_priority_cmd,
118 "[no] vrrp (1-255)$vrid priority (1-254)",
119 NO_STR
120 VRRP_STR
121 VRRP_VRID_STR
122 VRRP_PRIORITY_STR
123 "Priority value")
124 {
125 VTY_DECLVAR_CONTEXT(interface, ifp);
126
127 struct vrrp_vrouter *vr;
128 uint8_t newprio = no ? VRRP_DEFAULT_PRIORITY : priority;
129
130 VROUTER_GET_VTY(vty, ifp, vrid, vr);
131
132 vrrp_set_priority(vr, newprio);
133
134 return CMD_SUCCESS;
135 }
136
137 DEFPY(vrrp_advertisement_interval,
138 vrrp_advertisement_interval_cmd,
139 "[no] vrrp (1-255)$vrid advertisement-interval (1-4096)",
140 NO_STR VRRP_STR VRRP_VRID_STR VRRP_ADVINT_STR
141 "Advertisement interval in centiseconds")
142 {
143 VTY_DECLVAR_CONTEXT(interface, ifp);
144
145 struct vrrp_vrouter *vr;
146 uint16_t newadvint = no ? VRRP_DEFAULT_ADVINT : advertisement_interval;
147
148 VROUTER_GET_VTY(vty, ifp, vrid, vr);
149 vrrp_set_advertisement_interval(vr, newadvint);
150
151 return CMD_SUCCESS;
152 }
153
154 DEFPY(vrrp_ip,
155 vrrp_ip_cmd,
156 "[no] vrrp (1-255)$vrid ip A.B.C.D",
157 NO_STR
158 VRRP_STR
159 VRRP_VRID_STR
160 "Add IPv4 address\n"
161 VRRP_IP_STR)
162 {
163 VTY_DECLVAR_CONTEXT(interface, ifp);
164
165 struct vrrp_vrouter *vr;
166 bool deactivated = false;
167 bool activated = false;
168 bool failed = false;
169 int ret = CMD_SUCCESS;
170
171 VROUTER_GET_VTY(vty, ifp, vrid, vr);
172
173 bool will_activate = (vr->v4->fsm.state == VRRP_STATE_INITIALIZE);
174
175 if (no) {
176 int oldstate = vr->v4->fsm.state;
177 failed = vrrp_del_ipv4(vr, ip);
178 vrrp_check_start(vr);
179 deactivated = (vr->v4->fsm.state == VRRP_STATE_INITIALIZE
180 && oldstate != VRRP_STATE_INITIALIZE);
181 } else {
182 int oldstate = vr->v4->fsm.state;
183 failed = vrrp_add_ipv4(vr, ip);
184 vrrp_check_start(vr);
185 activated = (vr->v4->fsm.state != VRRP_STATE_INITIALIZE
186 && oldstate == VRRP_STATE_INITIALIZE);
187 }
188
189 if (activated)
190 vty_out(vty, "%% Activated IPv4 Virtual Router %ld\n", vrid);
191 if (deactivated)
192 vty_out(vty, "%% Deactivated IPv4 Virtual Router %ld\n", vrid);
193 if (failed) {
194 vty_out(vty, "%% Failed to %s virtual IP\n",
195 no ? "remove" : "add");
196 ret = CMD_WARNING_CONFIG_FAILED;
197 if (will_activate && !activated) {
198 vty_out(vty,
199 "%% Failed to activate IPv4 Virtual Router %ld\n",
200 vrid);
201 }
202 }
203
204 return ret;
205 }
206
207 DEFPY(vrrp_ip6,
208 vrrp_ip6_cmd,
209 "[no] vrrp (1-255)$vrid ipv6 X:X::X:X",
210 NO_STR
211 VRRP_STR
212 VRRP_VRID_STR
213 "Add IPv6 address\n"
214 VRRP_IP_STR)
215 {
216 VTY_DECLVAR_CONTEXT(interface, ifp);
217
218 struct vrrp_vrouter *vr;
219 bool deactivated = false;
220 bool activated = false;
221 bool failed = false;
222 int ret = CMD_SUCCESS;
223
224 VROUTER_GET_VTY(vty, ifp, vrid, vr);
225
226 if (vr->version != 3) {
227 vty_out(vty,
228 "%% Cannot add IPv6 address to VRRPv2 virtual router\n");
229 return CMD_WARNING_CONFIG_FAILED;
230 }
231
232 bool will_activate = (vr->v6->fsm.state == VRRP_STATE_INITIALIZE);
233
234 if (no) {
235 int oldstate = vr->v6->fsm.state;
236 failed = vrrp_del_ipv6(vr, ipv6);
237 deactivated = (vr->v6->fsm.state == VRRP_STATE_INITIALIZE
238 && oldstate != VRRP_STATE_INITIALIZE);
239 } else {
240 int oldstate = vr->v6->fsm.state;
241 failed = vrrp_add_ipv6(vr, ipv6);
242 activated = (vr->v6->fsm.state != VRRP_STATE_INITIALIZE
243 && oldstate == VRRP_STATE_INITIALIZE);
244 }
245
246 if (activated)
247 vty_out(vty, "%% Activated IPv6 Virtual Router %ld\n", vrid);
248 if (deactivated)
249 vty_out(vty, "%% Deactivated IPv6 Virtual Router %ld\n", vrid);
250 if (failed) {
251 vty_out(vty, "%% Failed to %s virtual IP\n",
252 no ? "remove" : "add");
253 ret = CMD_WARNING_CONFIG_FAILED;
254 if (will_activate && !activated) {
255 vty_out(vty,
256 "%% Failed to activate IPv6 Virtual Router %ld\n",
257 vrid);
258 }
259 }
260
261 return ret;
262 }
263
264 DEFPY(vrrp_preempt,
265 vrrp_preempt_cmd,
266 "[no] vrrp (1-255)$vrid preempt",
267 NO_STR
268 VRRP_STR
269 VRRP_VRID_STR
270 "Preempt mode\n")
271 {
272 VTY_DECLVAR_CONTEXT(interface, ifp);
273
274 struct vrrp_vrouter *vr;
275
276 VROUTER_GET_VTY(vty, ifp, vrid, vr);
277
278 vr->preempt_mode = !no;
279
280 return CMD_SUCCESS;
281 }
282
283 DEFPY(vrrp_autoconfigure,
284 vrrp_autoconfigure_cmd,
285 "[no] vrrp autoconfigure [version (2-3)]",
286 NO_STR
287 VRRP_STR
288 "Automatically set up VRRP instances on VRRP-compatible interfaces\n"
289 "Version for automatically configured instances\n"
290 VRRP_VERSION_STR)
291 {
292 version = version ? version : 3;
293
294 if (!no)
295 vrrp_autoconfig_on(version);
296 else
297 vrrp_autoconfig_off();
298
299 return CMD_SUCCESS;
300 }
301
302 static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
303 {
304 char ethstr4[ETHER_ADDR_STRLEN];
305 char ethstr6[ETHER_ADDR_STRLEN];
306 char ipstr[INET6_ADDRSTRLEN];
307 const char *stastr4 = vrrp_state_names[vr->v4->fsm.state];
308 const char *stastr6 = vrrp_state_names[vr->v6->fsm.state];
309 struct listnode *ln;
310 struct ipaddr *ip;
311
312 struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
313
314 ttable_add_row(tt, "%s|%" PRIu32, "Virtual Router ID", vr->vrid);
315 ttable_add_row(tt, "%s|%" PRIu8, "Protocol Version", vr->version);
316 ttable_add_row(tt, "%s|%s", "Autoconfigured",
317 vr->autoconf ? "Yes" : "No");
318 ttable_add_row(tt, "%s|%s", "Shutdown", vr->shutdown ? "Yes" : "No");
319 ttable_add_row(tt, "%s|%s", "Interface", vr->ifp->name);
320 prefix_mac2str(&vr->v4->vmac, ethstr4, sizeof(ethstr4));
321 prefix_mac2str(&vr->v6->vmac, ethstr6, sizeof(ethstr6));
322 ttable_add_row(tt, "%s|%s", "VRRP interface (v4)",
323 vr->v4->mvl_ifp ? vr->v4->mvl_ifp->name : "None");
324 ttable_add_row(tt, "%s|%s", "VRRP interface (v6)",
325 vr->v6->mvl_ifp ? vr->v6->mvl_ifp->name : "None");
326 ttable_add_row(tt, "%s|%s", "Virtual MAC (v4)", ethstr4);
327 ttable_add_row(tt, "%s|%s", "Virtual MAC (v6)", ethstr6);
328 ttable_add_row(tt, "%s|%s", "Status (v4)", stastr4);
329 ttable_add_row(tt, "%s|%s", "Status (v6)", stastr6);
330 ttable_add_row(tt, "%s|%" PRIu8, "Priority", vr->priority);
331 ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v4)",
332 vr->v4->priority);
333 ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v6)",
334 vr->v6->priority);
335 ttable_add_row(tt, "%s|%s", "Preempt Mode",
336 vr->preempt_mode ? "Yes" : "No");
337 ttable_add_row(tt, "%s|%s", "Accept Mode",
338 vr->accept_mode ? "Yes" : "No");
339 ttable_add_row(tt, "%s|%" PRIu16" cs", "Advertisement Interval",
340 vr->advertisement_interval);
341 ttable_add_row(tt, "%s|%" PRIu16" cs", "Master Advertisement Interval (v4)",
342 vr->v4->master_adver_interval);
343 ttable_add_row(tt, "%s|%" PRIu16" cs", "Master Advertisement Interval (v6)",
344 vr->v6->master_adver_interval);
345 ttable_add_row(tt, "%s|%" PRIu16" cs", "Skew Time (v4)", vr->v4->skew_time);
346 ttable_add_row(tt, "%s|%" PRIu16" cs", "Skew Time (v6)", vr->v6->skew_time);
347 ttable_add_row(tt, "%s|%" PRIu16" cs", "Master Down Interval (v4)",
348 vr->v4->master_down_interval);
349 ttable_add_row(tt, "%s|%" PRIu16" cs", "Master Down Interval (v6)",
350 vr->v6->master_down_interval);
351 ttable_add_row(tt, "%s|%u", "IPv4 Addresses", vr->v4->addrs->count);
352
353 char fill[35];
354 memset(fill, '.', sizeof(fill));
355 fill[sizeof(fill) - 1] = 0x00;
356 if (vr->v4->addrs->count) {
357 for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ln, ip)) {
358 inet_ntop(vr->v4->family, &ip->ipaddr_v4, ipstr,
359 sizeof(ipstr));
360 ttable_add_row(tt, "%s|%s", fill, ipstr);
361 }
362 }
363
364 ttable_add_row(tt, "%s|%u", "IPv6 Addresses", vr->v6->addrs->count);
365
366 if (vr->v6->addrs->count) {
367 for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ln, ip)) {
368 inet_ntop(vr->v6->family, &ip->ipaddr_v6, ipstr,
369 sizeof(ipstr));
370 ttable_add_row(tt, "%s|%s", fill, ipstr);
371 }
372 }
373
374 char *table = ttable_dump(tt, "\n");
375 vty_out(vty, "\n%s\n", table);
376 XFREE(MTYPE_TMP, table);
377 ttable_del(tt);
378
379 }
380
381 DEFPY(vrrp_vrid_show,
382 vrrp_vrid_show_cmd,
383 "show vrrp [interface INTERFACE$ifn] [(1-255)$vrid]",
384 SHOW_STR
385 VRRP_STR
386 INTERFACE_STR
387 "Only show VRRP instances on this interface\n"
388 VRRP_VRID_STR)
389 {
390 struct vrrp_vrouter *vr;
391 struct listnode *ln;
392 struct list *ll = hash_to_list(vrrp_vrouters_hash);
393
394 for (ALL_LIST_ELEMENTS_RO(ll, ln, vr)) {
395 if (ifn && !strmatch(ifn, vr->ifp->name))
396 continue;
397 if (vrid && vrid != vr->vrid)
398 continue;
399
400 vrrp_show(vty, vr);
401 }
402
403 list_delete(&ll);
404
405 return CMD_SUCCESS;
406 }
407
408
409 DEFPY(debug_vrrp,
410 debug_vrrp_cmd,
411 "[no] debug vrrp [{protocol$proto|autoconfigure$ac|packets$pkt|sockets$sock|ndisc$ndisc|arp$arp|zebra$zebra}]",
412 NO_STR
413 DEBUG_STR
414 VRRP_STR
415 "Debug protocol state\n"
416 "Debug autoconfiguration\n"
417 "Debug sent and received packets\n"
418 "Debug socket creation and configuration\n"
419 "Debug Neighbor Discovery\n"
420 "Debug ARP\n"
421 "Debug Zebra events\n")
422 {
423 /* If no specific are given on/off them all */
424 if (strmatch(argv[argc - 1]->text, "vrrp"))
425 vrrp_debug_set(NULL, 0, vty->node, !no, true, true, true, true,
426 true, true, true);
427 else
428 vrrp_debug_set(NULL, 0, vty->node, !no, !!proto, !!ac, !!pkt,
429 !!sock, !!ndisc, !!arp, !!zebra);
430
431 return CMD_SUCCESS;
432 }
433
434 DEFUN_NOSH (show_debugging_vrrp,
435 show_debugging_vrrp_cmd,
436 "show debugging [vrrp]",
437 SHOW_STR
438 DEBUG_STR
439 "VRRP information\n")
440 {
441 vty_out(vty, "VRRP debugging status:\n");
442
443 vrrp_debug_status_write(vty);
444
445 return CMD_SUCCESS;
446 }
447
448 /* clang-format on */
449
450 static struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1};
451 static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
452 static struct cmd_node vrrp_node = {VRRP_NODE, "", 1};
453
454 void vrrp_vty_init(void)
455 {
456 install_node(&debug_node, vrrp_config_write_debug);
457 install_node(&interface_node, vrrp_config_write_interface);
458 install_node(&vrrp_node, vrrp_config_write_global);
459 if_cmd_init();
460
461 install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
462 install_element(VIEW_NODE, &show_debugging_vrrp_cmd);
463 install_element(VIEW_NODE, &debug_vrrp_cmd);
464 install_element(CONFIG_NODE, &debug_vrrp_cmd);
465 install_element(CONFIG_NODE, &vrrp_autoconfigure_cmd);
466 install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
467 install_element(INTERFACE_NODE, &vrrp_shutdown_cmd);
468 install_element(INTERFACE_NODE, &vrrp_priority_cmd);
469 install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd);
470 install_element(INTERFACE_NODE, &vrrp_ip_cmd);
471 install_element(INTERFACE_NODE, &vrrp_ip6_cmd);
472 install_element(INTERFACE_NODE, &vrrp_preempt_cmd);
473 }