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