LCOV - code coverage report
Current view: top level - plugins/af_packet - cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 6 93 6.5 %
Date: 2023-07-05 22:20:52 Functions: 9 12 75.0 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * af_packet.c - linux kernel packet interface
       4             :  *
       5             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at:
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  *------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include <fcntl.h>                /* for open */
      21             : #include <sys/ioctl.h>
      22             : #include <sys/socket.h>
      23             : #include <sys/stat.h>
      24             : #include <sys/types.h>
      25             : #include <sys/uio.h>              /* for iovec */
      26             : #include <netinet/in.h>
      27             : 
      28             : #include <vlib/vlib.h>
      29             : #include <vlib/unix/unix.h>
      30             : #include <vnet/ip/ip.h>
      31             : #include <vnet/ethernet/ethernet.h>
      32             : 
      33             : #include <af_packet/af_packet.h>
      34             : 
      35             : /**
      36             :  * @file
      37             :  * @brief CLI for Host Interface Device Driver.
      38             :  *
      39             :  * This file contains the source code for CLI for the host interface.
      40             :  */
      41             : 
      42             : static clib_error_t *
      43           0 : af_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
      44             :                              vlib_cli_command_t * cmd)
      45             : {
      46           0 :   unformat_input_t _line_input, *line_input = &_line_input;
      47           0 :   af_packet_create_if_arg_t _arg, *arg = &_arg;
      48           0 :   clib_error_t *error = NULL;
      49             :   u8 hwaddr[6];
      50             :   int r;
      51             : 
      52           0 :   clib_memset (arg, 0, sizeof (*arg));
      53             : 
      54             :   // Default mode
      55           0 :   arg->mode = AF_PACKET_IF_MODE_ETHERNET;
      56             : 
      57             :   // Default number of rx/tx queue(s)
      58           0 :   arg->num_rxqs = 1;
      59           0 :   arg->num_txqs = 1;
      60             : 
      61             :   // Default flags
      62           0 :   arg->flags = AF_PACKET_IF_FLAGS_QDISC_BYPASS | AF_PACKET_IF_FLAGS_CKSUM_GSO;
      63             : 
      64             :   /* Get a line of input. */
      65           0 :   if (!unformat_user (input, unformat_line_input, line_input))
      66           0 :     return 0;
      67             : 
      68           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
      69             :     {
      70           0 :       if (unformat (line_input, "name %s", &arg->host_if_name))
      71             :         ;
      72           0 :       else if (unformat (line_input, "rx-size %u", &arg->rx_frame_size))
      73             :         ;
      74           0 :       else if (unformat (line_input, "tx-size %u", &arg->tx_frame_size))
      75             :         ;
      76           0 :       else if (unformat (line_input, "rx-per-block %u",
      77             :                          &arg->rx_frames_per_block))
      78             :         ;
      79           0 :       else if (unformat (line_input, "tx-per-block %u",
      80             :                          &arg->tx_frames_per_block))
      81             :         ;
      82           0 :       else if (unformat (line_input, "num-rx-queues %u", &arg->num_rxqs))
      83             :         ;
      84           0 :       else if (unformat (line_input, "num-tx-queues %u", &arg->num_txqs))
      85             :         ;
      86           0 :       else if (unformat (line_input, "qdisc-bypass-disable"))
      87           0 :         arg->flags &= ~AF_PACKET_IF_FLAGS_QDISC_BYPASS;
      88           0 :       else if (unformat (line_input, "cksum-gso-disable"))
      89           0 :         arg->flags &= ~AF_PACKET_IF_FLAGS_CKSUM_GSO;
      90           0 :       else if (unformat (line_input, "mode ip"))
      91           0 :         arg->mode = AF_PACKET_IF_MODE_IP;
      92           0 :       else if (unformat (line_input, "v2"))
      93           0 :         arg->is_v2 = 1;
      94           0 :       else if (unformat (line_input, "hw-addr %U", unformat_ethernet_address,
      95             :                          hwaddr))
      96           0 :         arg->hw_addr = hwaddr;
      97             :       else
      98             :         {
      99           0 :           error = clib_error_return (0, "unknown input `%U'",
     100             :                                      format_unformat_error, line_input);
     101           0 :           goto done;
     102             :         }
     103             :     }
     104             : 
     105           0 :   if (arg->host_if_name == NULL)
     106             :     {
     107           0 :       error = clib_error_return (0, "missing host interface name");
     108           0 :       goto done;
     109             :     }
     110             : 
     111           0 :   r = af_packet_create_if (arg);
     112             : 
     113           0 :   if (r == VNET_API_ERROR_SYSCALL_ERROR_1)
     114             :     {
     115           0 :       error = clib_error_return (0, "%s (errno %d)", strerror (errno), errno);
     116           0 :       goto done;
     117             :     }
     118             : 
     119           0 :   if (r == VNET_API_ERROR_INVALID_INTERFACE)
     120             :     {
     121           0 :       error = clib_error_return (0, "Invalid interface name");
     122           0 :       goto done;
     123             :     }
     124             : 
     125           0 :   if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS)
     126             :     {
     127           0 :       error = clib_error_return (0, "Interface already exists");
     128           0 :       goto done;
     129             :     }
     130             : 
     131           0 :   vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
     132             :                    arg->sw_if_index);
     133             : 
     134           0 : done:
     135           0 :   vec_free (arg->host_if_name);
     136           0 :   unformat_free (line_input);
     137             : 
     138           0 :   return error;
     139             : }
     140             : 
     141             : /*?
     142             :  * Create a host interface that will attach to a linux AF_PACKET
     143             :  * interface, one side of a veth pair. The veth pair must already
     144             :  * exist. Once created, a new host interface will exist in VPP
     145             :  * with the name '<em>host-<ifname></em>', where '<em><ifname></em>'
     146             :  * is the name of the specified veth pair. Use the
     147             :  * '<em>show interface</em>' command to display host interface details.
     148             :  *
     149             :  * This command has the following optional parameters:
     150             :  *
     151             :  * - <b>hw-addr <mac-addr></b> - Optional ethernet address, can be in either
     152             :  * X:X:X:X:X:X unix or X.X.X cisco format.
     153             :  *
     154             :  * @cliexpar
     155             :  * Example of how to create a host interface tied to one side of an
     156             :  * existing linux veth pair named vpp1:
     157             :  * @cliexstart{create host-interface name vpp1}
     158             :  * host-vpp1
     159             :  * @cliexend
     160             :  * Once the host interface is created, enable the interface using:
     161             :  * @cliexcmd{set interface state host-vpp1 up}
     162             : ?*/
     163      259447 : VLIB_CLI_COMMAND (af_packet_create_command, static) = {
     164             :   .path = "create host-interface",
     165             :   .short_help = "create host-interface [v2] name <ifname> [num-rx-queues <n>] "
     166             :                 "[num-tx-queues <n>] [hw-addr <mac-addr>] [mode ip] "
     167             :                 "[qdisc-bypass-disable] [cksum-gso-disable]",
     168             :   .function = af_packet_create_command_fn,
     169             : };
     170             : 
     171             : static clib_error_t *
     172           0 : af_packet_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
     173             :                              vlib_cli_command_t * cmd)
     174             : {
     175           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     176           0 :   u8 *host_if_name = NULL;
     177           0 :   clib_error_t *error = NULL;
     178             : 
     179             :   /* Get a line of input. */
     180           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     181           0 :     return 0;
     182             : 
     183           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     184             :     {
     185           0 :       if (unformat (line_input, "name %s", &host_if_name))
     186             :         ;
     187             :       else
     188             :         {
     189           0 :           error = clib_error_return (0, "unknown input `%U'",
     190             :                                      format_unformat_error, line_input);
     191           0 :           goto done;
     192             :         }
     193             :     }
     194             : 
     195           0 :   if (host_if_name == NULL)
     196             :     {
     197           0 :       error = clib_error_return (0, "missing host interface name");
     198           0 :       goto done;
     199             :     }
     200             : 
     201           0 :   af_packet_delete_if (host_if_name);
     202             : 
     203           0 : done:
     204           0 :   vec_free (host_if_name);
     205           0 :   unformat_free (line_input);
     206             : 
     207           0 :   return error;
     208             : }
     209             : 
     210             : /*?
     211             :  * Delete a host interface. Use the linux interface name to identify
     212             :  * the host interface to be deleted. In VPP, host interfaces are
     213             :  * named as '<em>host-<ifname></em>', where '<em><ifname></em>'
     214             :  * is the name of the linux interface.
     215             :  *
     216             :  * @cliexpar
     217             :  * Example of how to delete a host interface named host-vpp1:
     218             :  * @cliexcmd{delete host-interface name vpp1}
     219             : ?*/
     220      259447 : VLIB_CLI_COMMAND (af_packet_delete_command, static) = {
     221             :   .path = "delete host-interface",
     222             :   .short_help = "delete host-interface name <ifname>",
     223             :   .function = af_packet_delete_command_fn,
     224             : };
     225             : 
     226             : static clib_error_t *
     227           0 : af_packet_set_l4_cksum_offload_command_fn (vlib_main_t * vm,
     228             :                                            unformat_input_t * input,
     229             :                                            vlib_cli_command_t * cmd)
     230             : {
     231           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     232           0 :   u8 set = 0;
     233           0 :   clib_error_t *error = NULL;
     234           0 :   vnet_main_t *vnm = vnet_get_main ();
     235             :   u32 sw_if_index;
     236             : 
     237           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     238           0 :     return 0;
     239             : 
     240           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     241             :     {
     242           0 :       if (unformat (line_input, "%U", unformat_vnet_sw_interface, vnm,
     243             :                     &sw_if_index))
     244             :         ;
     245           0 :       else if (unformat (line_input, "on"))
     246           0 :         set = 1;
     247           0 :       else if (unformat (line_input, "off"))
     248           0 :         set = 0;
     249             :       else
     250             :         {
     251           0 :           error = clib_error_return (0, "unknown input '%U'",
     252             :                                      format_unformat_error, line_input);
     253           0 :           goto done;
     254             :         }
     255             :     }
     256             : 
     257           0 :   if (af_packet_set_l4_cksum_offload (sw_if_index, set) < 0)
     258           0 :     error = clib_error_return (0, "not an af_packet interface");
     259             : 
     260           0 : done:
     261           0 :   unformat_free (line_input);
     262           0 :   return error;
     263             : }
     264             : 
     265             : /*?
     266             :  * Set TCP/UDP offload checksum calculation. Use interface
     267             :  * name to identify the interface to set TCP/UDP offload checksum
     268             :  * calculation.
     269             :  *
     270             :  * @cliexpar
     271             :  * Example of how to set TCP/UDP offload checksum calculation on host-vpp0:
     272             :  * @cliexcmd{set host-interface l4-cksum-offload host-vpp0 off}
     273             :  * @cliexcmd{set host-interface l4-cksum-offload host-vpp0 on}
     274             : ?*/
     275      259447 : VLIB_CLI_COMMAND (af_packet_set_l4_cksum_offload_command, static) = {
     276             :   .path = "set host-interface l4-cksum-offload",
     277             :   .short_help = "set host-interface l4-cksum-offload <host-if-name> <on|off>",
     278             :   .function = af_packet_set_l4_cksum_offload_command_fn,
     279             : };
     280             : 
     281             : clib_error_t *
     282         559 : af_packet_cli_init (vlib_main_t * vm)
     283             : {
     284         559 :   return 0;
     285             : }
     286             : 
     287        1119 : VLIB_INIT_FUNCTION (af_packet_cli_init);
     288             : 
     289             : /*
     290             :  * fd.io coding-style-patch-verification: ON
     291             :  *
     292             :  * Local Variables:
     293             :  * eval: (c-set-style "gnu")
     294             :  * End:
     295             :  */

Generated by: LCOV version 1.14