]> git.proxmox.com Git - mirror_frr.git/blob - vrrpd/vrrp_vty.c
vrrpd: same VRID, different interface
[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_vty.h"
31 #include "vrrp_memory.h"
32 #ifndef VTYSH_EXTRACT_PL
33 #include "vrrpd/vrrp_vty_clippy.c"
34 #endif
35
36
37 #define VRRP_STR "Virtual Router Redundancy Protocol\n"
38 #define VRRP_VRID_STR "Virtual Router ID\n"
39 #define VRRP_PRIORITY_STR "Virtual Router Priority\n"
40 #define VRRP_ADVINT_STR "Virtual Router Advertisement Interval\n"
41 #define VRRP_IP_STR "Virtual Router IPv4 address\n"
42
43 #define VROUTER_GET_VTY(_vty, _ifp, _vrid, _vr) \
44 do { \
45 _vr = vrrp_lookup(_ifp, _vrid); \
46 if (!_vr) { \
47 vty_out(_vty, \
48 "%% Please configure VRRP instance %u\n", \
49 (unsigned int)_vrid); \
50 return CMD_WARNING_CONFIG_FAILED; \
51 } \
52 } while (0);
53
54 DEFUN_NOSH (show_debugging_vrrpd,
55 show_debugging_vrrpd_cmd,
56 "show debugging [vrrp]",
57 SHOW_STR
58 DEBUG_STR
59 "VRRP information\n")
60 {
61 vty_out(vty, "VRRP debugging status\n");
62
63 return CMD_SUCCESS;
64 }
65
66 DEFPY(vrrp_vrid,
67 vrrp_vrid_cmd,
68 "[no] vrrp (1-255)$vrid",
69 NO_STR
70 VRRP_STR
71 VRRP_VRID_STR)
72 {
73 VTY_DECLVAR_CONTEXT(interface, ifp);
74
75 struct vrrp_vrouter *vr = vrrp_lookup(ifp, vrid);
76
77 if (no && vr)
78 vrrp_vrouter_destroy(vr);
79 else if (no && !vr)
80 vty_out(vty, "%% VRRP instance %ld does not exist on %s\n",
81 vrid, ifp->name);
82 else if (!vr)
83 vrrp_vrouter_create(ifp, vrid);
84 else if (vr)
85 vty_out(vty, "%% VRRP instance %ld already exists on %s\n",
86 vrid, ifp->name);
87
88 return CMD_SUCCESS;
89 }
90
91 DEFPY(vrrp_priority,
92 vrrp_priority_cmd,
93 "[no] vrrp (1-255)$vrid priority (1-254)",
94 NO_STR
95 VRRP_STR
96 VRRP_VRID_STR
97 VRRP_PRIORITY_STR
98 "Priority value")
99 {
100 VTY_DECLVAR_CONTEXT(interface, ifp);
101
102 struct vrrp_vrouter *vr;
103 struct vrrp_router *r;
104 bool nr[2] = { false, false };
105 int ret = CMD_SUCCESS;
106 uint8_t newprio = no ? VRRP_DEFAULT_PRIORITY : priority;
107
108 VROUTER_GET_VTY(vty, ifp, vrid, vr);
109
110 r = vr->v4;
111 for (int i = 0; i < 2; i++) {
112 nr[i] = r->is_active && r->fsm.state != VRRP_STATE_INITIALIZE
113 && vr->priority != newprio;
114 if (nr[i]) {
115 vty_out(vty,
116 "%% WARNING: Restarting %s Virtual Router %ld to update priority\n",
117 family2str(r->family), vrid);
118 (void)vrrp_event(r, VRRP_EVENT_SHUTDOWN);
119 }
120 r = vr->v6;
121 }
122
123 vrrp_set_priority(vr, newprio);
124
125 r = vr->v4;
126 for (int i = 0; i < 2; i++) {
127 if (nr[i]) {
128 ret = vrrp_event(r, VRRP_EVENT_STARTUP);
129 if (ret < 0)
130 vty_out(vty,
131 "%% Failed to start Virtual Router %ld (%s)\n",
132 vrid, family2str(r->family));
133 }
134 r = vr->v6;
135 }
136
137 return CMD_SUCCESS;
138 }
139
140 DEFPY(vrrp_advertisement_interval,
141 vrrp_advertisement_interval_cmd,
142 "[no] vrrp (1-255)$vrid advertisement-interval (1-4096)",
143 NO_STR VRRP_STR VRRP_VRID_STR VRRP_ADVINT_STR
144 "Advertisement interval in centiseconds")
145 {
146 VTY_DECLVAR_CONTEXT(interface, ifp);
147
148 struct vrrp_vrouter *vr;
149 uint16_t newadvint = no ? VRRP_DEFAULT_ADVINT : advertisement_interval;
150
151 VROUTER_GET_VTY(vty, ifp, vrid, vr);
152 vrrp_set_advertisement_interval(vr, newadvint);
153
154 return CMD_SUCCESS;
155 }
156
157 DEFPY(vrrp_ip,
158 vrrp_ip_cmd,
159 "[no] vrrp (1-255)$vrid ip A.B.C.D",
160 NO_STR
161 VRRP_STR
162 VRRP_VRID_STR
163 "Add IPv4 address\n"
164 VRRP_IP_STR)
165 {
166 VTY_DECLVAR_CONTEXT(interface, ifp);
167
168 struct vrrp_vrouter *vr;
169 int ret;
170
171 VROUTER_GET_VTY(vty, ifp, vrid, vr);
172 vrrp_add_ipv4(vr, ip);
173
174 if (vr->v4->fsm.state == VRRP_STATE_INITIALIZE) {
175 vty_out(vty, "%% Activating Virtual Router %ld\n", vrid);
176 ret = vrrp_event(vr->v4, VRRP_EVENT_STARTUP);
177 ret = ret < 0 ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
178
179 if (ret == CMD_WARNING_CONFIG_FAILED)
180 vty_out(vty, "%% Failed to start Virtual Router %ld\n",
181 vrid);
182 } else {
183 ret = CMD_SUCCESS;
184 }
185
186 return ret;
187 }
188
189 DEFPY(vrrp_ip6,
190 vrrp_ip6_cmd,
191 "[no] vrrp (1-255)$vrid ipv6 X:X::X:X",
192 NO_STR
193 VRRP_STR
194 VRRP_VRID_STR
195 "Add IPv6 address\n"
196 VRRP_IP_STR)
197 {
198 VTY_DECLVAR_CONTEXT(interface, ifp);
199
200 struct vrrp_vrouter *vr;
201 int ret;
202
203 VROUTER_GET_VTY(vty, ifp, vrid, vr);
204 vrrp_add_ipv6(vr, ipv6);
205
206 if (vr->v6->fsm.state == VRRP_STATE_INITIALIZE) {
207 vty_out(vty, "%% Activating Virtual Router %ld\n", vrid);
208 ret = vrrp_event(vr->v6, VRRP_EVENT_STARTUP);
209 ret = ret < 0 ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
210
211 if (ret == CMD_WARNING_CONFIG_FAILED)
212 vty_out(vty, "%% Failed to start Virtual Router %ld\n",
213 vrid);
214 } else {
215 ret = CMD_SUCCESS;
216 }
217
218 return ret;
219 }
220
221 static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
222 {
223 char ethstr4[ETHER_ADDR_STRLEN];
224 char ethstr6[ETHER_ADDR_STRLEN];
225 char ipstr[INET6_ADDRSTRLEN];
226 const char *stastr4 = vrrp_state_names[vr->v4->fsm.state];
227 const char *stastr6 = vrrp_state_names[vr->v6->fsm.state];
228 struct listnode *ln;
229 struct ipaddr *ip;
230
231 struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
232
233 ttable_add_row(tt, "%s|%" PRIu32, "Virtual Router ID", vr->vrid);
234 ttable_add_row(tt, "%s|%s", "Interface", vr->ifp->name);
235 prefix_mac2str(&vr->v4->vmac, ethstr4, sizeof(ethstr4));
236 prefix_mac2str(&vr->v6->vmac, ethstr6, sizeof(ethstr6));
237 ttable_add_row(tt, "%s|%s", "VRRP interface (v4)",
238 vr->v4->mvl_ifp ? vr->v4->mvl_ifp->name : "None");
239 ttable_add_row(tt, "%s|%s", "VRRP interface (v6)",
240 vr->v6->mvl_ifp ? vr->v6->mvl_ifp->name : "None");
241 ttable_add_row(tt, "%s|%s", "Virtual MAC (v4)", ethstr4);
242 ttable_add_row(tt, "%s|%s", "Virtual MAC (v6)", ethstr6);
243 ttable_add_row(tt, "%s|%s", "Status (v4)", stastr4);
244 ttable_add_row(tt, "%s|%s", "Status (v6)", stastr6);
245 ttable_add_row(tt, "%s|%" PRIu8, "Priority", vr->priority);
246 ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v4)",
247 vr->v4->priority);
248 ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v6)",
249 vr->v6->priority);
250 ttable_add_row(tt, "%s|%s", "Preempt Mode",
251 vr->preempt_mode ? "Yes" : "No");
252 ttable_add_row(tt, "%s|%s", "Accept Mode",
253 vr->accept_mode ? "Yes" : "No");
254 ttable_add_row(tt, "%s|%" PRIu16" cs", "Advertisement Interval",
255 vr->advertisement_interval);
256 ttable_add_row(tt, "%s|%" PRIu16" cs", "Master Advertisement Interval (v4)",
257 vr->v4->master_adver_interval);
258 ttable_add_row(tt, "%s|%" PRIu16" cs", "Master Advertisement Interval (v6)",
259 vr->v6->master_adver_interval);
260 ttable_add_row(tt, "%s|%" PRIu16" cs", "Skew Time (v4)", vr->v4->skew_time);
261 ttable_add_row(tt, "%s|%" PRIu16" cs", "Skew Time (v6)", vr->v6->skew_time);
262 ttable_add_row(tt, "%s|%" PRIu16" cs", "Master Down Interval (v4)",
263 vr->v4->master_down_interval);
264 ttable_add_row(tt, "%s|%" PRIu16" cs", "Master Down Interval (v6)",
265 vr->v6->master_down_interval);
266 ttable_add_row(tt, "%s|%u", "IPv4 Addresses", vr->v4->addrs->count);
267
268 char fill[37];
269 memset(fill, '.', sizeof(fill));
270 fill[sizeof(fill) - 1] = 0x00;
271 if (vr->v4->addrs->count) {
272 for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ln, ip)) {
273 inet_ntop(vr->v4->family, &ip->ipaddr_v4, ipstr,
274 sizeof(ipstr));
275 ttable_add_row(tt, "%s|%s", fill, ipstr);
276 }
277 }
278
279 ttable_add_row(tt, "%s|%u", "IPv6 Addresses", vr->v6->addrs->count);
280
281 if (vr->v6->addrs->count) {
282 for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ln, ip)) {
283 inet_ntop(vr->v6->family, &ip->ipaddr_v6, ipstr,
284 sizeof(ipstr));
285 ttable_add_row(tt, "%s|%s", fill, ipstr);
286 }
287 }
288
289 char *table = ttable_dump(tt, "\n");
290 vty_out(vty, "\n%s\n", table);
291 XFREE(MTYPE_TMP, table);
292 ttable_del(tt);
293
294 }
295
296 DEFPY(vrrp_vrid_show,
297 vrrp_vrid_show_cmd,
298 "show vrrp [interface INTERFACE$ifn] [(1-255)$vrid]",
299 SHOW_STR
300 VRRP_STR
301 INTERFACE_STR
302 "Only show VRRP instances on this interface\n"
303 VRRP_VRID_STR)
304 {
305 struct vrrp_vrouter *vr;
306 struct listnode *ln;
307 struct list *ll = hash_to_list(vrrp_vrouters_hash);
308
309 for (ALL_LIST_ELEMENTS_RO(ll, ln, vr)) {
310 if (ifn && !strmatch(ifn, vr->ifp->name))
311 continue;
312 if (vrid && vrid != vr->vrid)
313 continue;
314
315 vrrp_show(vty, vr);
316 }
317
318 list_delete(&ll);
319
320 return CMD_SUCCESS;
321 }
322
323 static struct cmd_node interface_node = {
324 INTERFACE_NODE,
325 "%s(config-if)# ", 1
326 };
327
328 void vrrp_vty_init(void)
329 {
330 install_node(&interface_node, NULL);
331 if_cmd_init();
332 install_element(VIEW_NODE, &show_debugging_vrrpd_cmd);
333 install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
334 install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
335 install_element(INTERFACE_NODE, &vrrp_priority_cmd);
336 install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd);
337 install_element(INTERFACE_NODE, &vrrp_ip_cmd);
338 install_element(INTERFACE_NODE, &vrrp_ip6_cmd);
339 }