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