LCOV - code coverage report
Current view: top level - plugins/vrrp - vrrp_cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 6 235 2.6 %
Date: 2023-10-26 01:39:38 Functions: 12 19 63.2 %

          Line data    Source code
       1             : /*
       2             :  * vrrp_cli.c - vrrp plugin debug CLI commands
       3             :  *
       4             :  * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
       5             :  *
       6             :  * SPDX-License-Identifier: Apache-2.0
       7             :  *
       8             :  */
       9             : 
      10             : #include <vnet/vnet.h>
      11             : #include <vnet/plugin/plugin.h>
      12             : #include <vrrp/vrrp.h>
      13             : 
      14             : #include <vlibapi/api.h>
      15             : #include <vlibmemory/api.h>
      16             : #include <vpp/app/version.h>
      17             : 
      18             : 
      19             : static clib_error_t *
      20           0 : vrrp_vr_add_del_command_fn (vlib_main_t * vm,
      21             :                             unformat_input_t * input,
      22             :                             vlib_cli_command_t * cmd, u8 is_add)
      23             : {
      24           0 :   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           0 :   clib_error_t *ret = 0;
      30             :   int rv;
      31             : 
      32           0 :   clib_memset (&vr_conf, 0, sizeof (vr_conf));
      33             : 
      34             :   /* RFC 5798 - preempt enabled by default */
      35           0 :   vr_conf.flags = VRRP_VR_PREEMPT;
      36             : 
      37           0 :   addrs = 0;
      38           0 :   n_addrs4 = n_addrs6 = 0;
      39             : 
      40             :   /* defaults */
      41           0 :   sw_if_index = ~0;
      42           0 :   vr_id = 0;
      43           0 :   priority = 100;
      44           0 :   interval = 100;
      45             : 
      46           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
      47             :     {
      48           0 :       clib_memset (&addr, 0, sizeof (addr));
      49             : 
      50           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
      51             :                     &sw_if_index))
      52             :         ;
      53           0 :       else if (unformat (input, "vr_id %u", &vr_id))
      54             :         ;
      55           0 :       else if (unformat (input, "ipv6"))
      56           0 :         vr_conf.flags |= VRRP_VR_IPV6;
      57           0 :       else if (unformat (input, "priority %u", &priority))
      58             :         ;
      59           0 :       else if (unformat (input, "interval %u", &interval))
      60             :         ;
      61           0 :       else if (unformat (input, "no_preempt"))
      62           0 :         vr_conf.flags &= ~VRRP_VR_PREEMPT;
      63           0 :       else if (unformat (input, "accept_mode"))
      64           0 :         vr_conf.flags |= VRRP_VR_ACCEPT;
      65           0 :       else if (unformat (input, "unicast"))
      66           0 :         vr_conf.flags |= VRRP_VR_UNICAST;
      67           0 :       else if (unformat (input, "%U", unformat_ip4_address, &addr.ip4))
      68             :         {
      69           0 :           n_addrs4++;
      70           0 :           vec_add1 (addrs, addr);
      71             :         }
      72           0 :       else if (unformat (input, "%U", unformat_ip6_address, &addr.ip6))
      73             :         {
      74           0 :           n_addrs6++;
      75           0 :           vec_add1 (addrs, addr);
      76             :         }
      77             :       else
      78           0 :         break;
      79             :     }
      80             : 
      81           0 :   if (sw_if_index == ~0)
      82           0 :     ret = clib_error_return (0, "Please specify an interface...");
      83           0 :   else if (!vr_id || vr_id > 0xff)
      84           0 :     ret = clib_error_return (0, "VR ID must be between 1 and 255...");
      85             : 
      86           0 :   if (is_add)
      87             :     {
      88           0 :       if (!priority || priority > 0xff)
      89           0 :         ret = clib_error_return (0, "priority must be between 1 and 255...");
      90           0 :       else if (interval > 0xffff)
      91           0 :         ret = clib_error_return (0, "interval must be <= 65535...");
      92           0 :       else if (n_addrs4 && (n_addrs6 || vr_conf.flags & VRRP_VR_IPV6))
      93           0 :         ret = clib_error_return (0, "Mismatched address families");
      94             :     }
      95             : 
      96           0 :   if (ret)                      /* data validation failed */
      97           0 :     goto done;
      98             : 
      99           0 :   vr_conf.sw_if_index = sw_if_index;
     100           0 :   vr_conf.vr_id = (u8) vr_id;
     101           0 :   vr_conf.priority = (u8) priority;
     102           0 :   vr_conf.adv_interval = (u16) interval;
     103           0 :   vr_conf.vr_addrs = addrs;
     104             : 
     105           0 :   rv = vrrp_vr_add_del (is_add, &vr_conf, NULL);
     106             : 
     107           0 :   switch (rv)
     108             :     {
     109           0 :     case 0:
     110           0 :       break;
     111             : 
     112             :       /* adding */
     113           0 :     case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
     114           0 :       ret = clib_error_return (0, "Failed to add VR that already exists");
     115           0 :       goto done;
     116             :       break;
     117             : 
     118           0 :     case VNET_API_ERROR_INVALID_SRC_ADDRESS:
     119           0 :       ret = clib_error_return (0, "Failed to add VR with no IP addresses");
     120           0 :       goto done;
     121             :       break;
     122             : 
     123           0 :     case VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE:
     124           0 :       ret = clib_error_return (0, "Failed to add VR with priority 255 - "
     125             :                                "VR IP addresses not configured on interface");
     126           0 :       goto done;
     127             :       break;
     128             : 
     129             :       /* deleting */
     130           0 :     case VNET_API_ERROR_NO_SUCH_ENTRY:
     131           0 :       ret = clib_error_return (0, "Failed to delete VR which does not exist");
     132           0 :       goto done;
     133             :       break;
     134             : 
     135           0 :     default:
     136           0 :       ret = clib_error_return (0, "vrrp_vr_add_del returned %d", rv);
     137           0 :       goto done;
     138             :       break;
     139             :     }
     140             : 
     141           0 : done:
     142           0 :   vec_free (addrs);
     143             : 
     144           0 :   return ret;
     145             : }
     146             : 
     147             : static clib_error_t *
     148           0 : vrrp_vr_add_command_fn (vlib_main_t * vm, unformat_input_t * input,
     149             :                         vlib_cli_command_t * cmd)
     150             : {
     151           0 :   return vrrp_vr_add_del_command_fn (vm, input, cmd, 1 /* is_add */ );
     152             : }
     153             : 
     154             : /* *INDENT-OFF* */
     155        8063 : VLIB_CLI_COMMAND (vrrp_vr_add_command, static) =
     156             : {
     157             :   .path = "vrrp vr add",
     158             :   .short_help =
     159             :   "vrrp vr add <interface> [vr_id <n>] [ipv6] [priority <value>] [interval <value>] [no_preempt] [accept_mode] [unicast] [<ip_addr> ...]",
     160             :   .function = vrrp_vr_add_command_fn,
     161             : };
     162             : /* *INDENT-ON* */
     163             : 
     164             : static clib_error_t *
     165           0 : vrrp_vr_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
     166             :                         vlib_cli_command_t * cmd)
     167             : {
     168           0 :   return vrrp_vr_add_del_command_fn (vm, input, cmd, 0 /* is_add */ );
     169             : }
     170             : 
     171             : /* *INDENT-OFF* */
     172        8063 : VLIB_CLI_COMMAND (vrrp_vr_del_command, static) =
     173             : {
     174             :   .path = "vrrp vr del",
     175             :   .short_help = "vrrp vr del <interface> [vr_id <n>] [ipv6]",
     176             :   .function = vrrp_vr_del_command_fn,
     177             : };
     178             : /* *INDENT-ON* */
     179             : 
     180             : static clib_error_t *
     181           0 : vrrp_show_vr_command_fn (vlib_main_t * vm,
     182             :                          unformat_input_t * input, vlib_cli_command_t * cmd)
     183             : {
     184           0 :   vrrp_main_t *vmp = &vrrp_main;
     185             :   vrrp_vr_t *vr;
     186           0 :   u32 sw_if_index = ~0;
     187             : 
     188           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     189             :     {
     190           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
     191             :                     &sw_if_index))
     192             :         ;
     193           0 :       else if (unformat (input, "sw_if_index %u", &sw_if_index))
     194             :         ;
     195             :       else
     196           0 :         break;
     197             :     }
     198             : 
     199           0 :   pool_foreach (vr, vmp->vrs)
     200             :   {
     201             : 
     202           0 :     if (sw_if_index && (sw_if_index != ~0) &&
     203           0 :         (sw_if_index != vr->config.sw_if_index))
     204           0 :       continue;
     205           0 :     vlib_cli_output (vm, "%U", format_vrrp_vr, vr);
     206             :   }
     207             : 
     208           0 :   return 0;
     209             : }
     210             : 
     211             : /* *INDENT-OFF* */
     212        8063 : VLIB_CLI_COMMAND (vrrp_show_vr_command, static) =
     213             : {
     214             :   .path = "show vrrp vr",
     215             :   .short_help =
     216             :   "show vrrp vr [(<intf_name>|sw_if_index <n>)]",
     217             :   .function = vrrp_show_vr_command_fn,
     218             : };
     219             : /* *INDENT-ON* */
     220             : 
     221             : static clib_error_t *
     222           0 : vrrp_proto_start_stop_command_fn (vlib_main_t * vm,
     223             :                                   unformat_input_t * input,
     224             :                                   vlib_cli_command_t * cmd)
     225             : {
     226           0 :   vrrp_main_t *vmp = &vrrp_main;
     227             :   vrrp_vr_key_t vr_key;
     228             :   u32 sw_if_index;
     229             :   u32 vr_id;
     230             :   u8 is_ipv6, is_start, is_stop;
     231             :   int rv;
     232             : 
     233           0 :   clib_memset (&vr_key, 0, sizeof (vr_key));
     234             : 
     235             :   /* defaults */
     236           0 :   sw_if_index = ~0;
     237           0 :   vr_id = 0;
     238           0 :   is_ipv6 = is_start = is_stop = 0;
     239             : 
     240           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     241             :     {
     242           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
     243             :                     &sw_if_index))
     244             :         ;
     245           0 :       else if (unformat (input, "sw_if_index %u", &sw_if_index))
     246             :         ;
     247           0 :       else if (unformat (input, "vr_id %u", &vr_id))
     248             :         ;
     249           0 :       else if (unformat (input, "ipv6"))
     250           0 :         is_ipv6 = 1;
     251           0 :       else if (unformat (input, "start"))
     252           0 :         is_start = 1;
     253           0 :       else if (unformat (input, "stop"))
     254           0 :         is_stop = 1;
     255             :       else
     256           0 :         return clib_error_return (0, "unknown input `%U'",
     257             :                                   format_unformat_error, input);
     258             :     }
     259             : 
     260           0 :   if (is_start == is_stop)
     261           0 :     return clib_error_return (0, "One of start or stop must be specified");
     262           0 :   else if (sw_if_index == ~0)
     263           0 :     return clib_error_return (0, "Please specify an interface...");
     264           0 :   else if (!vr_id)
     265           0 :     return clib_error_return (0, "Invalid VR ID...");
     266             : 
     267           0 :   vr_key.sw_if_index = sw_if_index;
     268           0 :   vr_key.vr_id = vr_id;
     269           0 :   vr_key.is_ipv6 = (is_ipv6 != 0);
     270             : 
     271           0 :   rv = vrrp_vr_start_stop (is_start, &vr_key);
     272             : 
     273           0 :   switch (rv)
     274             :     {
     275           0 :     case 0:
     276           0 :       break;
     277           0 :     case VNET_API_ERROR_INIT_FAILED:
     278           0 :       return clib_error_return (0, "Cannot start unicast VR without peers");
     279             :       break;
     280           0 :     default:
     281           0 :       return clib_error_return (0, "vrrp_vr_start_stop returned %d", rv);
     282             :       break;
     283             :     }
     284             : 
     285           0 :   return 0;
     286             : }
     287             : 
     288             : static clib_error_t *
     289           0 : vrrp_peers_command_fn (vlib_main_t * vm, unformat_input_t * input,
     290             :                        vlib_cli_command_t * cmd)
     291             : {
     292           0 :   vrrp_main_t *vmp = &vrrp_main;
     293             :   vrrp_vr_key_t vr_key;
     294             :   u32 sw_if_index;
     295             :   u32 vr_id;
     296             :   u8 is_ipv6;
     297             :   int rv;
     298             :   ip46_address_t addr, *addrs;
     299             :   u8 n_addrs4, n_addrs6;
     300           0 :   clib_error_t *ret = 0;
     301             : 
     302           0 :   clib_memset (&vr_key, 0, sizeof (vr_key));
     303             : 
     304             :   /* defaults */
     305           0 :   addrs = 0;
     306           0 :   n_addrs4 = n_addrs6 = 0;
     307           0 :   sw_if_index = ~0;
     308           0 :   vr_id = 0;
     309           0 :   is_ipv6 = 0;
     310             : 
     311           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     312             :     {
     313           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
     314             :                     &sw_if_index))
     315             :         ;
     316           0 :       else if (unformat (input, "sw_if_index %u", &sw_if_index))
     317             :         ;
     318           0 :       else if (unformat (input, "vr_id %u", &vr_id))
     319             :         ;
     320           0 :       else if (unformat (input, "ipv6"))
     321           0 :         is_ipv6 = 1;
     322           0 :       else if (unformat (input, "%U", unformat_ip4_address, &addr.ip4))
     323             :         {
     324           0 :           n_addrs4++;
     325           0 :           vec_add1 (addrs, addr);
     326             :         }
     327           0 :       else if (unformat (input, "%U", unformat_ip6_address, &addr.ip6))
     328             :         {
     329           0 :           n_addrs6++;
     330           0 :           vec_add1 (addrs, addr);
     331             :         }
     332             :       else
     333             :         {
     334           0 :           ret = clib_error_return (0, "unknown input `%U'",
     335             :                                    format_unformat_error, input);
     336           0 :           goto done;
     337             :         }
     338             :     }
     339             : 
     340           0 :   if (sw_if_index == ~0)
     341           0 :     ret = clib_error_return (0, "Please specify an interface...");
     342           0 :   else if (!vr_id)
     343           0 :     ret = clib_error_return (0, "Invalid VR ID...");
     344           0 :   else if (n_addrs4 && (n_addrs6 || is_ipv6))
     345           0 :     ret = clib_error_return (0, "Mismatched address families");
     346             : 
     347           0 :   if (ret)                      /* data validation failed */
     348           0 :     goto done;
     349             : 
     350           0 :   vr_key.sw_if_index = sw_if_index;
     351           0 :   vr_key.vr_id = vr_id;
     352           0 :   vr_key.is_ipv6 = (is_ipv6 != 0);
     353             : 
     354           0 :   rv = vrrp_vr_set_peers (&vr_key, addrs);
     355             : 
     356           0 :   switch (rv)
     357             :     {
     358           0 :     case 0:
     359           0 :       break;
     360           0 :     case VNET_API_ERROR_INVALID_ARGUMENT:
     361           0 :       ret = clib_error_return (0, "Peers can only be set on a unicast VR");
     362           0 :       break;
     363           0 :     case VNET_API_ERROR_RSRC_IN_USE:
     364           0 :       ret = clib_error_return (0, "Cannot set peers on a running VR");
     365           0 :       break;
     366           0 :     case VNET_API_ERROR_INVALID_DST_ADDRESS:
     367           0 :       ret = clib_error_return (0, "No peer addresses provided");
     368           0 :       break;
     369           0 :     default:
     370           0 :       ret = clib_error_return (0, "vrrp_vr_set_peers returned %d", rv);
     371           0 :       break;
     372             :     }
     373             : 
     374           0 : done:
     375           0 :   vec_free (addrs);
     376             : 
     377           0 :   return ret;
     378             : }
     379             : 
     380             : /* *INDENT-OFF* */
     381        8063 : VLIB_CLI_COMMAND (vrrp_proto_start_stop_command, static) =
     382             : {
     383             :   .path = "vrrp proto",
     384             :   .short_help =
     385             :   "vrrp proto (start|stop) (<intf_name>|sw_if_index <n>) vr_id <n> [ipv6]",
     386             :   .function = vrrp_proto_start_stop_command_fn,
     387             : };
     388             : /* *INDENT-ON* */
     389             : 
     390             : /* *INDENT-OFF* */
     391        8063 : VLIB_CLI_COMMAND (vrrp_peers_command, static) =
     392             : {
     393             :   .path = "vrrp peers",
     394             :   .short_help =
     395             :   "vrrp peers (<intf_name>|sw_if_index <n>) vr_id <n> [ipv6] <peer1_addr> [<peer2_addr> ...]",
     396             :   .function = vrrp_peers_command_fn,
     397             : };
     398             : /* *INDENT-ON* */
     399             : 
     400             : static clib_error_t *
     401           0 : vrrp_vr_track_if_command_fn (vlib_main_t * vm,
     402             :                              unformat_input_t * input,
     403             :                              vlib_cli_command_t * cmd)
     404             : {
     405           0 :   vnet_main_t *vnm = vnet_get_main ();
     406           0 :   vrrp_main_t *vmp = &vrrp_main;
     407             :   u32 sw_if_index, track_if_index, vr_id, priority;
     408           0 :   u8 is_ipv6 = 0;
     409           0 :   clib_error_t *ret = 0;
     410           0 :   vrrp_vr_tracking_if_t *track_intfs = 0, *track_intf;
     411             :   vrrp_vr_t *vr;
     412             :   u8 is_add, is_del;
     413             :   int rv;
     414             : 
     415             :   /* defaults */
     416           0 :   sw_if_index = ~0;
     417           0 :   vr_id = 0;
     418           0 :   is_add = is_del = 0;
     419             : 
     420           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     421             :     {
     422           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface, vmp->vnet_main,
     423             :                     &sw_if_index))
     424             :         ;
     425           0 :       else if (unformat (input, "sw_if_index %u", &sw_if_index))
     426             :         ;
     427           0 :       else if (unformat (input, "add"))
     428           0 :         is_add = 1;
     429           0 :       else if (unformat (input, "del"))
     430           0 :         is_del = 1;
     431           0 :       else if (unformat (input, "vr_id %u", &vr_id))
     432             :         ;
     433           0 :       else if (unformat (input, "ipv6"))
     434           0 :         is_ipv6 = 1;
     435           0 :       else if (unformat (input, "track-index %u priority %u", &track_if_index,
     436             :                          &priority))
     437             :         {
     438           0 :           vec_add2 (track_intfs, track_intf, 1);;
     439           0 :           track_intf->sw_if_index = track_if_index;
     440           0 :           track_intf->priority = priority;
     441             :         }
     442             :       else
     443           0 :         break;
     444             :     }
     445             : 
     446           0 :   if (sw_if_index == ~0)
     447           0 :     ret = clib_error_return (0, "Please specify an interface");
     448           0 :   else if (!vr_id || vr_id > 0xff)
     449           0 :     ret = clib_error_return (0, "VR ID must be between 1 and 255");
     450           0 :   else if (is_add == is_del)
     451           0 :     ret = clib_error_return (0, "One of add,delete must be specified");
     452             : 
     453           0 :   if (ret)
     454           0 :     goto done;
     455             : 
     456           0 :   vr = vrrp_vr_lookup (sw_if_index, vr_id, is_ipv6);
     457           0 :   if (!vr)
     458             :     {
     459           0 :       ret = clib_error_return (0, "VR not found");
     460           0 :       goto done;
     461             :     }
     462             : 
     463           0 :   vec_foreach (track_intf, track_intfs)
     464             :   {
     465           0 :     if (!vnet_sw_interface_is_valid (vnm, track_intf->sw_if_index))
     466             :       {
     467           0 :         ret = clib_error_return (0, "tracked intf sw_if_index %u invalid",
     468             :                                  track_intf->sw_if_index);
     469           0 :         goto done;
     470             :       }
     471           0 :     if (!track_intf->priority)
     472             :       {
     473           0 :         ret = clib_error_return (0, "tracked intf priority must be > 0");
     474           0 :         goto done;
     475             :       }
     476           0 :     if (track_intf->priority >= vr->config.priority)
     477             :       {
     478           0 :         ret = clib_error_return (0, "tracked intf priority must be less "
     479             :                                  "than VR priority (%u)",
     480             :                                  vr->config.priority);
     481           0 :         goto done;
     482             :       }
     483             :   }
     484             : 
     485           0 :   rv = vrrp_vr_tracking_ifs_add_del (vr, track_intfs, is_add);
     486           0 :   if (rv)
     487           0 :     ret = clib_error_return (0, "vrrp_vr_tracking_ifs_add_del returned %d",
     488             :                              rv);
     489             : 
     490           0 : done:
     491           0 :   vec_free (track_intfs);
     492             : 
     493           0 :   return ret;
     494             : }
     495             : 
     496             : /* *INDENT-OFF* */
     497        8063 : VLIB_CLI_COMMAND (vrrp_vr_track_if_command, static) =
     498             : {
     499             :   .path = "vrrp vr track-if",
     500             :   .short_help =
     501             :   "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> ...]",
     502             :   .function = vrrp_vr_track_if_command_fn,
     503             : };
     504             : /* *INDENT-ON* */
     505             : 
     506             : /*
     507             :  * fd.io coding-style-patch-verification: ON
     508             :  *
     509             :  * Local Variables:
     510             :  * eval: (c-set-style "gnu")
     511             :  * End:
     512             :  */

Generated by: LCOV version 1.14