LCOV - code coverage report
Current view: top level - plugins/memif - cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 8 212 3.8 %
Date: 2023-10-26 01:39:38 Functions: 13 22 59.1 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       4             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5             :  * you may not use this file except in compliance with the License.
       6             :  * You may obtain a copy of the License at:
       7             :  *
       8             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  * Unless required by applicable law or agreed to in writing, software
      11             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  * See the License for the specific language governing permissions and
      14             :  * limitations under the License.
      15             :  *------------------------------------------------------------------
      16             :  */
      17             : #include <stdint.h>
      18             : #include <net/if.h>
      19             : #include <sys/ioctl.h>
      20             : #include <inttypes.h>
      21             : 
      22             : #include <vlib/vlib.h>
      23             : #include <vlib/unix/unix.h>
      24             : #include <vnet/ethernet/ethernet.h>
      25             : 
      26             : #include <memif/memif.h>
      27             : #include <memif/private.h>
      28             : 
      29             : 
      30             : static clib_error_t *
      31           0 : memif_socket_filename_create_command_fn (vlib_main_t * vm,
      32             :                                          unformat_input_t * input,
      33             :                                          vlib_cli_command_t * cmd)
      34             : {
      35           0 :   unformat_input_t _line_input, *line_input = &_line_input;
      36             :   clib_error_t *err;
      37             :   u32 socket_id;
      38             :   u8 *socket_filename;
      39             : 
      40             :   /* Get a line of input. */
      41           0 :   if (!unformat_user (input, unformat_line_input, line_input))
      42           0 :     return 0;
      43             : 
      44           0 :   socket_id = ~0;
      45           0 :   socket_filename = 0;
      46             : 
      47           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
      48             :     {
      49           0 :       if (unformat (line_input, "id %u", &socket_id))
      50             :         ;
      51           0 :       else if (unformat (line_input, "filename %s", &socket_filename))
      52             :         ;
      53             :       else
      54             :         {
      55           0 :           vec_free (socket_filename);
      56           0 :           unformat_free (line_input);
      57           0 :           return clib_error_return (0, "unknown input `%U'",
      58             :                                     format_unformat_error, input);
      59             :         }
      60             :     }
      61             : 
      62           0 :   unformat_free (line_input);
      63             : 
      64           0 :   if (socket_id == 0 || socket_id == ~0)
      65             :     {
      66           0 :       vec_free (socket_filename);
      67           0 :       return clib_error_return (0, "Invalid socket id");
      68             :     }
      69             : 
      70           0 :   if (!socket_filename || *socket_filename == 0)
      71             :     {
      72           0 :       vec_free (socket_filename);
      73           0 :       return clib_error_return (0, "Invalid socket filename");
      74             :     }
      75             : 
      76           0 :   err = memif_socket_filename_add_del (1, socket_id, (char *) socket_filename);
      77             : 
      78           0 :   vec_free (socket_filename);
      79             : 
      80           0 :   return err;
      81             : }
      82             : 
      83             : /* *INDENT-OFF* */
      84      108439 : VLIB_CLI_COMMAND (memif_socket_filename_create_command, static) = {
      85             :   .path = "create memif socket",
      86             :   .short_help = "create memif socket [id <id>] [filename <path>]",
      87             :   .function = memif_socket_filename_create_command_fn,
      88             : };
      89             : /* *INDENT-ON* */
      90             : 
      91             : static clib_error_t *
      92           0 : memif_socket_filename_delete_command_fn (vlib_main_t * vm,
      93             :                                          unformat_input_t * input,
      94             :                                          vlib_cli_command_t * cmd)
      95             : {
      96           0 :   unformat_input_t _line_input, *line_input = &_line_input;
      97             :   u32 socket_id;
      98             : 
      99             :   /* Get a line of input. */
     100           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     101           0 :     return 0;
     102             : 
     103           0 :   socket_id = ~0;
     104             : 
     105           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     106             :     {
     107           0 :       if (unformat (line_input, "id %u", &socket_id))
     108             :         ;
     109             :       else
     110             :         {
     111           0 :           unformat_free (line_input);
     112           0 :           return clib_error_return (0, "unknown input `%U'",
     113             :                                     format_unformat_error, input);
     114             :         }
     115             :     }
     116             : 
     117           0 :   unformat_free (line_input);
     118             : 
     119           0 :   if (socket_id == 0 || socket_id == ~0)
     120             :     {
     121           0 :       return clib_error_return (0, "Invalid socket id");
     122             :     }
     123             : 
     124           0 :   return memif_socket_filename_add_del (0, socket_id, 0);
     125             : }
     126             : 
     127             : /* *INDENT-OFF* */
     128      108439 : VLIB_CLI_COMMAND (memif_socket_filename_delete_command, static) = {
     129             :   .path = "delete memif socket",
     130             :   .short_help = "delete memif socket [id <id>]",
     131             :   .function = memif_socket_filename_delete_command_fn,
     132             : };
     133             : /* *INDENT-ON* */
     134             : 
     135             : static clib_error_t *
     136           0 : memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
     137             :                          vlib_cli_command_t * cmd)
     138             : {
     139           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     140             :   clib_error_t *err;
     141           0 :   u32 ring_size = MEMIF_DEFAULT_RING_SIZE;
     142           0 :   memif_create_if_args_t args = { 0 };
     143           0 :   args.buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
     144           0 :   u32 rx_queues = MEMIF_DEFAULT_RX_QUEUES;
     145           0 :   u32 tx_queues = MEMIF_DEFAULT_TX_QUEUES;
     146             : 
     147             :   /* Get a line of input. */
     148           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     149           0 :     return 0;
     150             : 
     151           0 :   args.is_zero_copy = 1;
     152             : 
     153           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     154             :     {
     155           0 :       if (unformat (line_input, "id %u", &args.id))
     156             :         ;
     157           0 :       else if (unformat (line_input, "socket-id %u", &args.socket_id))
     158             :         ;
     159           0 :       else if (unformat (line_input, "secret %s", &args.secret))
     160             :         ;
     161           0 :       else if (unformat (line_input, "ring-size %u", &ring_size))
     162             :         ;
     163           0 :       else if (unformat (line_input, "rx-queues %u", &rx_queues))
     164             :         ;
     165           0 :       else if (unformat (line_input, "tx-queues %u", &tx_queues))
     166             :         ;
     167           0 :       else if (unformat (line_input, "buffer-size %u", &args.buffer_size))
     168             :         ;
     169           0 :       else if (unformat (line_input, "master"))
     170           0 :         args.is_master = 1;
     171           0 :       else if (unformat (line_input, "slave"))
     172           0 :         args.is_master = 0;
     173           0 :       else if (unformat (line_input, "no-zero-copy"))
     174           0 :         args.is_zero_copy = 0;
     175           0 :       else if (unformat (line_input, "use-dma"))
     176           0 :         args.use_dma = 1;
     177           0 :       else if (unformat (line_input, "mode ip"))
     178           0 :         args.mode = MEMIF_INTERFACE_MODE_IP;
     179           0 :       else if (unformat (line_input, "hw-addr %U",
     180             :                          unformat_ethernet_address, args.hw_addr))
     181           0 :         args.hw_addr_set = 1;
     182             :       else
     183             :         {
     184           0 :           unformat_free (line_input);
     185           0 :           return clib_error_return (0, "unknown input `%U'",
     186             :                                     format_unformat_error, input);
     187             :         }
     188             :     }
     189           0 :   unformat_free (line_input);
     190             : 
     191           0 :   if (!is_pow2 (ring_size))
     192           0 :     return clib_error_return (0, "ring size must be power of 2");
     193             : 
     194           0 :   if (ring_size > 32768)
     195           0 :     return clib_error_return (0, "maximum ring size is 32768");
     196             : 
     197           0 :   args.log2_ring_size = min_log2 (ring_size);
     198             : 
     199           0 :   if (rx_queues > 255 || rx_queues < 1)
     200           0 :     return clib_error_return (0, "rx queue must be between 1 - 255");
     201           0 :   if (tx_queues > 255 || tx_queues < 1)
     202           0 :     return clib_error_return (0, "tx queue must be between 1 - 255");
     203             : 
     204           0 :   args.rx_queues = rx_queues;
     205           0 :   args.tx_queues = tx_queues;
     206             : 
     207           0 :   err = memif_create_if (vm, &args);
     208             : 
     209           0 :   vec_free (args.secret);
     210             : 
     211           0 :   return err;
     212             : }
     213             : 
     214             : /* *INDENT-OFF* */
     215      108439 : VLIB_CLI_COMMAND (memif_create_command, static) = {
     216             :   .path = "create interface memif",
     217             :   .short_help = "create interface memif [id <id>] [socket-id <socket-id>] "
     218             :                 "[ring-size <size>] [buffer-size <size>] "
     219             :                 "[hw-addr <mac-address>] "
     220             :                 "<master|slave> [rx-queues <number>] [tx-queues <number>] "
     221             :                 "[mode ip] [secret <string>]",
     222             :   .function = memif_create_command_fn,
     223             : };
     224             : /* *INDENT-ON* */
     225             : 
     226             : static clib_error_t *
     227           0 : memif_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
     228             :                          vlib_cli_command_t * cmd)
     229             : {
     230           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     231           0 :   u32 sw_if_index = ~0;
     232             :   vnet_hw_interface_t *hw;
     233           0 :   memif_main_t *mm = &memif_main;
     234             :   memif_if_t *mif;
     235           0 :   vnet_main_t *vnm = vnet_get_main ();
     236             : 
     237             :   /* Get a line of input. */
     238           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     239           0 :     return 0;
     240             : 
     241           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     242             :     {
     243           0 :       if (unformat (line_input, "sw_if_index %d", &sw_if_index))
     244             :         ;
     245           0 :       else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
     246             :                          vnm, &sw_if_index))
     247             :         ;
     248             :       else
     249             :         {
     250           0 :           unformat_free (line_input);
     251           0 :           return clib_error_return (0, "unknown input `%U'",
     252             :                                     format_unformat_error, input);
     253             :         }
     254             :     }
     255           0 :   unformat_free (line_input);
     256             : 
     257           0 :   if (sw_if_index == ~0)
     258           0 :     return clib_error_return (0,
     259             :                               "please specify interface name or sw_if_index");
     260             : 
     261           0 :   hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
     262           0 :   if (hw == NULL || memif_device_class.index != hw->dev_class_index)
     263           0 :     return clib_error_return (0, "not a memif interface");
     264             : 
     265           0 :   mif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
     266           0 :   memif_delete_if (vm, mif);
     267             : 
     268           0 :   return 0;
     269             : }
     270             : 
     271             : /* *INDENT-OFF* */
     272      108439 : VLIB_CLI_COMMAND (memif_delete_command, static) = {
     273             :   .path = "delete interface memif",
     274             :   .short_help = "delete interface memif {<interface> | sw_if_index <sw_idx>}",
     275             :   .function = memif_delete_command_fn,
     276             : };
     277             : /* *INDENT-ON* */
     278             : 
     279             : static u8 *
     280           0 : format_memif_if_flags (u8 * s, va_list * args)
     281             : {
     282           0 :   u32 flags = va_arg (*args, u32);
     283             : #define _(a,b,c) if ( flags & (1 << a)) s = format (s, " %s", c);
     284           0 :   foreach_memif_if_flag
     285             : #undef _
     286           0 :     return s;
     287             : }
     288             : 
     289             : static u8 *
     290           0 : format_memif_if_mode (u8 * s, va_list * args)
     291             : {
     292           0 :   memif_if_t *mif = va_arg (*args, memif_if_t *);
     293           0 :   if (mif->mode == MEMIF_INTERFACE_MODE_ETHERNET)
     294           0 :     return format (s, "ethernet");
     295           0 :   if (mif->mode == MEMIF_INTERFACE_MODE_IP)
     296           0 :     return format (s, "ip");
     297           0 :   if (mif->mode == MEMIF_INTERFACE_MODE_PUNT_INJECT)
     298           0 :     return format (s, "punt-inject");
     299           0 :   return format (s, "unknown mode (%u)", mif->mode);;
     300             : }
     301             : 
     302             : static u8 *
     303           0 : format_memif_queue (u8 * s, va_list * args)
     304             : {
     305           0 :   memif_queue_t *mq = va_arg (*args, memif_queue_t *);
     306           0 :   uword i = va_arg (*args, uword);
     307           0 :   u32 indent = format_get_indent (s);
     308             : 
     309           0 :   s = format (s, "%U%s ring %u:\n",
     310             :               format_white_space, indent,
     311           0 :               (mq->type == MEMIF_RING_S2M) ?
     312             :               "slave-to-master" : "master-to-slave", i);
     313           0 :   s = format (s, "%Uregion %u offset %u ring-size %u int-fd %d\n",
     314             :               format_white_space, indent + 4,
     315           0 :               mq->region, mq->offset, (1 << mq->log2_ring_size), mq->int_fd);
     316             : 
     317           0 :   if (mq->ring)
     318           0 :     s = format (s, "%Uhead %u tail %u flags 0x%04x interrupts %u\n",
     319             :                 format_white_space, indent + 4,
     320           0 :                 mq->ring->head, mq->ring->tail, mq->ring->flags,
     321             :                 mq->int_count);
     322             : 
     323           0 :   return s;
     324             : }
     325             : 
     326             : static u8 *
     327           0 : format_memif_descriptor (u8 * s, va_list * args)
     328             : {
     329           0 :   memif_if_t *mif = va_arg (*args, memif_if_t *);
     330           0 :   memif_queue_t *mq = va_arg (*args, memif_queue_t *);
     331           0 :   u32 indent = format_get_indent (s);
     332             :   memif_ring_t *ring;
     333             :   u16 ring_size;
     334             :   u16 slot;
     335             : 
     336           0 :   ring_size = 1 << mq->log2_ring_size;
     337           0 :   ring = mq->ring;
     338           0 :   if (ring)
     339             :     {
     340           0 :       s = format (s, "%Udescriptor table:\n", format_white_space, indent);
     341           0 :       s = format (s,
     342             :                   "%Uid    flags region len         address         offset    "
     343             :                   "    user address\n",
     344             :                   format_white_space, indent);
     345           0 :       s = format (s,
     346             :                   "%U===== ===== ====== ======== ================== "
     347             :                   "========== ==================\n",
     348             :                   format_white_space, indent);
     349           0 :       for (slot = 0; slot < ring_size; slot++)
     350             :         {
     351           0 :           s = format (s, "%U%-5d %-5d %-6d %-7d  0x%016lx %-10d 0x%016lx\n",
     352           0 :                       format_white_space, indent, slot, ring->desc[slot].flags,
     353           0 :                       ring->desc[slot].region, ring->desc[slot].length,
     354           0 :                       mif->regions[ring->desc[slot].region].shm,
     355             :                       ring->desc[slot].offset,
     356             :                       memif_get_buffer (mif, ring, slot));
     357             :         }
     358           0 :       s = format (s, "\n");
     359             :     }
     360             : 
     361           0 :   return s;
     362             : }
     363             : 
     364             : static clib_error_t *
     365           0 : memif_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
     366             :                        vlib_cli_command_t * cmd)
     367             : {
     368           0 :   memif_main_t *mm = &memif_main;
     369             :   memif_if_t *mif;
     370           0 :   vnet_main_t *vnm = vnet_get_main ();
     371             :   memif_region_t *mr;
     372             :   memif_queue_t *mq;
     373             :   uword i;
     374           0 :   int show_descr = 0;
     375           0 :   clib_error_t *error = 0;
     376           0 :   u32 hw_if_index, *hw_if_indices = 0;
     377             :   u32 sock_id;
     378             :   u32 msf_idx;
     379           0 :   u8 *s = 0;
     380             : 
     381           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     382             :     {
     383           0 :       if (unformat
     384             :           (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
     385           0 :         vec_add1 (hw_if_indices, hw_if_index);
     386           0 :       else if (unformat (input, "descriptors"))
     387           0 :         show_descr = 1;
     388             :       else
     389             :         {
     390           0 :           error = clib_error_return (0, "unknown input `%U'",
     391             :                                      format_unformat_error, input);
     392           0 :           goto done;
     393             :         }
     394             :     }
     395             : 
     396           0 :   vlib_cli_output (vm, "sockets\n");
     397           0 :   vlib_cli_output (vm, "  %-3s %-11s %s\n", "id", "listener", "filename");
     398             : 
     399             :   /* *INDENT-OFF* */
     400           0 :   hash_foreach (sock_id, msf_idx, mm->socket_file_index_by_sock_id,
     401             :     ({
     402             :       memif_socket_file_t *msf;
     403             :       u8 *filename;
     404             : 
     405             :       msf = pool_elt_at_index(mm->socket_files, msf_idx);
     406             :       filename = msf->filename;
     407             :       if (msf->is_listener)
     408             :         s = format (s, "yes (%u)", msf->ref_cnt);
     409             :       else
     410             :         s = format (s, "no");
     411             : 
     412             :       vlib_cli_output(vm, "  %-3u %-11v %s\n", sock_id, s, filename);
     413             :       vec_reset_length (s);
     414             :     }));
     415             :   /* *INDENT-ON* */
     416           0 :   vec_free (s);
     417             : 
     418           0 :   vlib_cli_output (vm, "\n");
     419             : 
     420           0 :   if (vec_len (hw_if_indices) == 0)
     421             :     {
     422             :       /* *INDENT-OFF* */
     423           0 :       pool_foreach (mif, mm->interfaces)
     424           0 :           vec_add1 (hw_if_indices, mif->hw_if_index);
     425             :       /* *INDENT-ON* */
     426             :     }
     427             : 
     428           0 :   for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
     429             :     {
     430             :       vnet_hw_interface_t *hi =
     431           0 :         vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
     432           0 :       mif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
     433           0 :       memif_socket_file_t *msf = vec_elt_at_index (mm->socket_files,
     434             :                                                    mif->socket_file_index);
     435           0 :       vlib_cli_output (vm, "interface %U", format_vnet_sw_if_index_name,
     436             :                        vnm, mif->sw_if_index);
     437           0 :       if (mif->remote_name)
     438           0 :         vlib_cli_output (vm, "  remote-name \"%s\"", mif->remote_name);
     439           0 :       if (mif->remote_if_name)
     440           0 :         vlib_cli_output (vm, "  remote-interface \"%s\"",
     441             :                          mif->remote_if_name);
     442           0 :       vlib_cli_output (vm, "  socket-id %u id %u mode %U", msf->socket_id,
     443             :                        mif->id, format_memif_if_mode, mif);
     444           0 :       vlib_cli_output (vm, "  flags%U", format_memif_if_flags, mif->flags);
     445           0 :       vlib_cli_output (vm, "  listener-fd %d conn-fd %d",
     446           0 :                        msf->sock ? msf->sock->fd : 0,
     447           0 :                        mif->sock ? mif->sock->fd : 0);
     448           0 :       vlib_cli_output (vm, "  num-s2m-rings %u num-m2s-rings %u "
     449             :                        "buffer-size %u num-regions %u",
     450           0 :                        mif->run.num_s2m_rings, mif->run.num_m2s_rings,
     451           0 :                        mif->run.buffer_size, vec_len (mif->regions));
     452             : 
     453           0 :       if (mif->local_disc_string)
     454           0 :         vlib_cli_output (vm, "  local-disc-reason \"%s\"",
     455             :                          mif->local_disc_string);
     456           0 :       if (mif->remote_disc_string)
     457           0 :         vlib_cli_output (vm, "  remote-disc-reason \"%s\"",
     458             :                          mif->remote_disc_string);
     459             : 
     460             :       /* *INDENT-OFF* */
     461           0 :       vec_foreach_index (i, mif->regions)
     462             :         {
     463           0 :           mr = vec_elt_at_index (mif->regions, i);
     464           0 :           vlib_cli_output (vm, "  region %u size %u fd %d", i,
     465             :                            mr->region_size, mr->fd);
     466             :         }
     467           0 :       vec_foreach_index (i, mif->tx_queues)
     468             :         {
     469           0 :           mq = vec_elt_at_index (mif->tx_queues, i);
     470           0 :           vlib_cli_output (vm, "  %U", format_memif_queue, mq, i);
     471           0 :           if (show_descr)
     472           0 :             vlib_cli_output (vm, "  %U", format_memif_descriptor, mif, mq);
     473             :         }
     474           0 :       vec_foreach_index (i, mif->rx_queues)
     475             :         {
     476           0 :           mq = vec_elt_at_index (mif->rx_queues, i);
     477           0 :           vlib_cli_output (vm, "  %U", format_memif_queue, mq, i);
     478           0 :           if (show_descr)
     479           0 :             vlib_cli_output (vm, "  %U", format_memif_descriptor, mif, mq);
     480             :         }
     481             :       /* *INDENT-ON* */
     482             :     }
     483           0 : done:
     484           0 :   vec_free (hw_if_indices);
     485           0 :   return error;
     486             : }
     487             : 
     488             : /* *INDENT-OFF* */
     489      108439 : VLIB_CLI_COMMAND (memif_show_command, static) = {
     490             :   .path = "show memif",
     491             :   .short_help = "show memif [<interface>] [descriptors]",
     492             :   .function = memif_show_command_fn,
     493             : };
     494             : /* *INDENT-ON* */
     495             : 
     496             : clib_error_t *
     497         575 : memif_cli_init (vlib_main_t * vm)
     498             : {
     499         575 :   return 0;
     500             : }
     501             : 
     502        1151 : VLIB_INIT_FUNCTION (memif_cli_init);
     503             : 
     504             : /*
     505             :  * fd.io coding-style-patch-verification: ON
     506             :  *
     507             :  * Local Variables:
     508             :  * eval: (c-set-style "gnu")
     509             :  * End:
     510             :  */

Generated by: LCOV version 1.14