2 * vrrp_cli.c - vrrp plugin debug CLI commands
4 * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
6 * SPDX-License-Identifier: Apache-2.0
10 #include <vnet/vnet.h>
11 #include <vnet/plugin/plugin.h>
12 #include <vrrp/vrrp.h>
14 #include <vlibapi/api.h>
15 #include <vlibmemory/api.h>
16 #include <vpp/app/version.h>
20 vrrp_vr_add_del_command_fn (vlib_main_t * vm,
21 unformat_input_t * input,
22 vlib_cli_command_t * cmd, u8 is_add)
24 vrrp_main_t *vmp = &vrrp_main;
25 vrrp_vr_config_t vr_conf;
26 u32 sw_if_index, vr_id, priority, interval;
27 ip46_address_t addr, *addrs;
28 u8 n_addrs4, n_addrs6;
29 clib_error_t *ret = 0;
32 clib_memset (&vr_conf, 0, sizeof (vr_conf));
34 /* RFC 5798 - preempt enabled by default */
35 vr_conf.flags = VRRP_VR_PREEMPT;
38 n_addrs4 = n_addrs6 = 0;
46 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
48 clib_memset (&addr, 0, sizeof (addr));
50 if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
53 else if (unformat (input, "vr_id %u", &vr_id))
55 else if (unformat (input, "ipv6"))
56 vr_conf.flags |= VRRP_VR_IPV6;
57 else if (unformat (input, "priority %u", &priority))
59 else if (unformat (input, "interval %u", &interval))
61 else if (unformat (input, "no_preempt"))
62 vr_conf.flags &= ~VRRP_VR_PREEMPT;
63 else if (unformat (input, "accept_mode"))
64 vr_conf.flags |= VRRP_VR_ACCEPT;
65 else if (unformat (input, "unicast"))
66 vr_conf.flags |= VRRP_VR_UNICAST;
67 else if (unformat (input, "%U", unformat_ip4_address, &addr.ip4))
70 vec_add1 (addrs, addr);
72 else if (unformat (input, "%U", unformat_ip6_address, &addr.ip6))
75 vec_add1 (addrs, addr);
81 if (sw_if_index == ~0)
82 ret = clib_error_return (0, "Please specify an interface...");
83 else if (!vr_id || vr_id > 0xff)
84 ret = clib_error_return (0, "VR ID must be between 1 and 255...");
88 if (!priority || priority > 0xff)
89 ret = clib_error_return (0, "priority must be between 1 and 255...");
90 else if (interval > 0xffff)
91 ret = clib_error_return (0, "interval must be <= 65535...");
92 else if (n_addrs4 && (n_addrs6 || vr_conf.flags & VRRP_VR_IPV6))
93 ret = clib_error_return (0, "Mismatched address families");
96 if (ret) /* data validation failed */
99 vr_conf.sw_if_index = sw_if_index;
100 vr_conf.vr_id = (u8) vr_id;
101 vr_conf.priority = (u8) priority;
102 vr_conf.adv_interval = (u16) interval;
103 vr_conf.vr_addrs = addrs;
105 rv = vrrp_vr_add_del (is_add, &vr_conf, NULL);
113 case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
114 ret = clib_error_return (0, "Failed to add VR that already exists");
118 case VNET_API_ERROR_INVALID_SRC_ADDRESS:
119 ret = clib_error_return (0, "Failed to add VR with no IP addresses");
123 case VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE:
124 ret = clib_error_return (0, "Failed to add VR with priority 255 - "
125 "VR IP addresses not configured on interface");
130 case VNET_API_ERROR_NO_SUCH_ENTRY:
131 ret = clib_error_return (0, "Failed to delete VR which does not exist");
136 ret = clib_error_return (0, "vrrp_vr_add_del returned %d", rv);
147 static clib_error_t *
148 vrrp_vr_add_command_fn (vlib_main_t * vm, unformat_input_t * input,
149 vlib_cli_command_t * cmd)
151 return vrrp_vr_add_del_command_fn (vm, input, cmd, 1 /* is_add */ );
154 VLIB_CLI_COMMAND (vrrp_vr_add_command, static) =
156 .path = "vrrp vr add",
158 "vrrp vr add <interface> [vr_id <n>] [ipv6] [priority <value>] [interval <value>] [no_preempt] [accept_mode] [unicast] [<ip_addr> ...]",
159 .function = vrrp_vr_add_command_fn,
162 static clib_error_t *
163 vrrp_vr_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
164 vlib_cli_command_t * cmd)
166 return vrrp_vr_add_del_command_fn (vm, input, cmd, 0 /* is_add */ );
169 VLIB_CLI_COMMAND (vrrp_vr_del_command, static) =
171 .path = "vrrp vr del",
172 .short_help = "vrrp vr del <interface> [vr_id <n>] [ipv6]",
173 .function = vrrp_vr_del_command_fn,
176 static clib_error_t *
177 vrrp_show_vr_command_fn (vlib_main_t * vm,
178 unformat_input_t * input, vlib_cli_command_t * cmd)
180 vrrp_main_t *vmp = &vrrp_main;
182 u32 sw_if_index = ~0;
184 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
186 if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
189 else if (unformat (input, "sw_if_index %u", &sw_if_index))
195 pool_foreach (vr, vmp->vrs)
198 if (sw_if_index && (sw_if_index != ~0) &&
199 (sw_if_index != vr->config.sw_if_index))
201 vlib_cli_output (vm, "%U", format_vrrp_vr, vr);
207 VLIB_CLI_COMMAND (vrrp_show_vr_command, static) =
209 .path = "show vrrp vr",
211 "show vrrp vr [(<intf_name>|sw_if_index <n>)]",
212 .function = vrrp_show_vr_command_fn,
215 static clib_error_t *
216 vrrp_proto_start_stop_command_fn (vlib_main_t * vm,
217 unformat_input_t * input,
218 vlib_cli_command_t * cmd)
220 vrrp_main_t *vmp = &vrrp_main;
221 vrrp_vr_key_t vr_key;
224 u8 is_ipv6, is_start, is_stop;
227 clib_memset (&vr_key, 0, sizeof (vr_key));
232 is_ipv6 = is_start = is_stop = 0;
234 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
236 if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
239 else if (unformat (input, "sw_if_index %u", &sw_if_index))
241 else if (unformat (input, "vr_id %u", &vr_id))
243 else if (unformat (input, "ipv6"))
245 else if (unformat (input, "start"))
247 else if (unformat (input, "stop"))
250 return clib_error_return (0, "unknown input `%U'",
251 format_unformat_error, input);
254 if (is_start == is_stop)
255 return clib_error_return (0, "One of start or stop must be specified");
256 else if (sw_if_index == ~0)
257 return clib_error_return (0, "Please specify an interface...");
259 return clib_error_return (0, "Invalid VR ID...");
261 vr_key.sw_if_index = sw_if_index;
262 vr_key.vr_id = vr_id;
263 vr_key.is_ipv6 = (is_ipv6 != 0);
265 rv = vrrp_vr_start_stop (is_start, &vr_key);
271 case VNET_API_ERROR_INIT_FAILED:
272 return clib_error_return (0, "Cannot start unicast VR without peers");
275 return clib_error_return (0, "vrrp_vr_start_stop returned %d", rv);
282 static clib_error_t *
283 vrrp_peers_command_fn (vlib_main_t * vm, unformat_input_t * input,
284 vlib_cli_command_t * cmd)
286 vrrp_main_t *vmp = &vrrp_main;
287 vrrp_vr_key_t vr_key;
292 ip46_address_t addr, *addrs;
293 u8 n_addrs4, n_addrs6;
294 clib_error_t *ret = 0;
296 clib_memset (&vr_key, 0, sizeof (vr_key));
300 n_addrs4 = n_addrs6 = 0;
305 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
307 if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
310 else if (unformat (input, "sw_if_index %u", &sw_if_index))
312 else if (unformat (input, "vr_id %u", &vr_id))
314 else if (unformat (input, "ipv6"))
316 else if (unformat (input, "%U", unformat_ip4_address, &addr.ip4))
319 vec_add1 (addrs, addr);
321 else if (unformat (input, "%U", unformat_ip6_address, &addr.ip6))
324 vec_add1 (addrs, addr);
328 ret = clib_error_return (0, "unknown input `%U'",
329 format_unformat_error, input);
334 if (sw_if_index == ~0)
335 ret = clib_error_return (0, "Please specify an interface...");
337 ret = clib_error_return (0, "Invalid VR ID...");
338 else if (n_addrs4 && (n_addrs6 || is_ipv6))
339 ret = clib_error_return (0, "Mismatched address families");
341 if (ret) /* data validation failed */
344 vr_key.sw_if_index = sw_if_index;
345 vr_key.vr_id = vr_id;
346 vr_key.is_ipv6 = (is_ipv6 != 0);
348 rv = vrrp_vr_set_peers (&vr_key, addrs);
354 case VNET_API_ERROR_INVALID_ARGUMENT:
355 ret = clib_error_return (0, "Peers can only be set on a unicast VR");
357 case VNET_API_ERROR_RSRC_IN_USE:
358 ret = clib_error_return (0, "Cannot set peers on a running VR");
360 case VNET_API_ERROR_INVALID_DST_ADDRESS:
361 ret = clib_error_return (0, "No peer addresses provided");
364 ret = clib_error_return (0, "vrrp_vr_set_peers returned %d", rv);
374 VLIB_CLI_COMMAND (vrrp_proto_start_stop_command, static) =
376 .path = "vrrp proto",
378 "vrrp proto (start|stop) (<intf_name>|sw_if_index <n>) vr_id <n> [ipv6]",
379 .function = vrrp_proto_start_stop_command_fn,
382 VLIB_CLI_COMMAND (vrrp_peers_command, static) =
384 .path = "vrrp peers",
386 "vrrp peers (<intf_name>|sw_if_index <n>) vr_id <n> [ipv6] <peer1_addr> [<peer2_addr> ...]",
387 .function = vrrp_peers_command_fn,
390 static clib_error_t *
391 vrrp_vr_track_if_command_fn (vlib_main_t * vm,
392 unformat_input_t * input,
393 vlib_cli_command_t * cmd)
395 vnet_main_t *vnm = vnet_get_main ();
396 vrrp_main_t *vmp = &vrrp_main;
397 u32 sw_if_index, track_if_index, vr_id, priority;
399 clib_error_t *ret = 0;
400 vrrp_vr_tracking_if_t *track_intfs = 0, *track_intf;
410 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
412 if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
415 else if (unformat (input, "sw_if_index %u", &sw_if_index))
417 else if (unformat (input, "add"))
419 else if (unformat (input, "del"))
421 else if (unformat (input, "vr_id %u", &vr_id))
423 else if (unformat (input, "ipv6"))
425 else if (unformat (input, "track-index %u priority %u", &track_if_index,
428 vec_add2 (track_intfs, track_intf, 1);;
429 track_intf->sw_if_index = track_if_index;
430 track_intf->priority = priority;
436 if (sw_if_index == ~0)
437 ret = clib_error_return (0, "Please specify an interface");
438 else if (!vr_id || vr_id > 0xff)
439 ret = clib_error_return (0, "VR ID must be between 1 and 255");
440 else if (is_add == is_del)
441 ret = clib_error_return (0, "One of add,delete must be specified");
446 vr = vrrp_vr_lookup (sw_if_index, vr_id, is_ipv6);
449 ret = clib_error_return (0, "VR not found");
453 vec_foreach (track_intf, track_intfs)
455 if (!vnet_sw_interface_is_valid (vnm, track_intf->sw_if_index))
457 ret = clib_error_return (0, "tracked intf sw_if_index %u invalid",
458 track_intf->sw_if_index);
461 if (!track_intf->priority)
463 ret = clib_error_return (0, "tracked intf priority must be > 0");
466 if (track_intf->priority >= vr->config.priority)
468 ret = clib_error_return (0, "tracked intf priority must be less "
469 "than VR priority (%u)",
470 vr->config.priority);
475 rv = vrrp_vr_tracking_ifs_add_del (vr, track_intfs, is_add);
477 ret = clib_error_return (0, "vrrp_vr_tracking_ifs_add_del returned %d",
481 vec_free (track_intfs);
486 VLIB_CLI_COMMAND (vrrp_vr_track_if_command, static) =
488 .path = "vrrp vr track-if",
490 "vrrp vr track-if (add|del) (<intf_name>|sw_if_index <n>) vr_id <n> [ipv6] track-index <n> priority <n> [ track-index <n> priority <n> ...]",
491 .function = vrrp_vr_track_if_command_fn,
495 * fd.io coding-style-patch-verification: ON
498 * eval: (c-set-style "gnu")