LCOV - code coverage report
Current view: top level - plugins/memif - memif_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 116 183 63.4 %
Date: 2023-10-26 01:39:38 Functions: 8 10 80.0 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * memif_api.c - memif api
       4             :  *
       5             :  * Copyright (c) 2017 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 <vlib/vlib.h>
      21             : #include <vnet/ethernet/ethernet.h>
      22             : #include <vlib/unix/unix.h>
      23             : #include <memif/memif.h>
      24             : #include <memif/private.h>
      25             : 
      26             : #include <vlibapi/api.h>
      27             : #include <vlibmemory/api.h>
      28             : 
      29             : #include <vnet/ip/ip_types_api.h>
      30             : #include <vnet/ethernet/ethernet_types_api.h>
      31             : 
      32             : /* define message IDs */
      33             : #include <vnet/format_fns.h>
      34             : #include <memif/memif.api_enum.h>
      35             : #include <memif/memif.api_types.h>
      36             : 
      37             : #define REPLY_MSG_ID_BASE mm->msg_id_base
      38             : #include <vlibapi/api_helper_macros.h>
      39             : 
      40             : /**
      41             :  * @brief Message handler for memif_socket_filename_add_del API.
      42             :  * @param mp the vl_api_memif_socket_filename_add_del_t API message
      43             :  */
      44             : void
      45          24 :   vl_api_memif_socket_filename_add_del_t_handler
      46             :   (vl_api_memif_socket_filename_add_del_t * mp)
      47             : {
      48          24 :   memif_main_t *mm = &memif_main;
      49             :   u8 is_add;
      50             :   u32 socket_id;
      51             :   vl_api_memif_socket_filename_add_del_reply_t *rmp;
      52             :   int rv;
      53             : 
      54             :   /* is_add */
      55          24 :   is_add = mp->is_add;
      56             : 
      57             :   /* socket_id */
      58          24 :   socket_id = clib_net_to_host_u32 (mp->socket_id);
      59          24 :   if (socket_id == 0 || socket_id == ~0)
      60             :     {
      61           0 :       rv = VNET_API_ERROR_INVALID_ARGUMENT;
      62           0 :       goto reply;
      63             :     }
      64             : 
      65             :   /* socket filename */
      66          24 :   mp->socket_filename[ARRAY_LEN (mp->socket_filename) - 1] = 0;
      67             : 
      68          24 :   rv = vnet_get_api_error_and_free (memif_socket_filename_add_del (
      69          24 :     is_add, socket_id, (char *) mp->socket_filename));
      70             : 
      71          24 : reply:
      72          24 :   REPLY_MACRO (VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_REPLY);
      73             : }
      74             : 
      75             : /**
      76             :  * @brief Message handler for memif_socket_filename_add_del API.
      77             :  * @param mp the vl_api_memif_socket_filename_add_del_t API message
      78             :  */
      79             : void
      80           0 : vl_api_memif_socket_filename_add_del_v2_t_handler (
      81             :   vl_api_memif_socket_filename_add_del_v2_t *mp)
      82             : {
      83             :   vl_api_memif_socket_filename_add_del_v2_reply_t *rmp;
      84           0 :   memif_main_t *mm = &memif_main;
      85           0 :   char *socket_filename = 0;
      86             :   u32 socket_id;
      87             :   int rv;
      88             : 
      89             :   /* socket_id */
      90           0 :   socket_id = clib_net_to_host_u32 (mp->socket_id);
      91           0 :   if (socket_id == 0)
      92             :     {
      93           0 :       rv = VNET_API_ERROR_INVALID_ARGUMENT;
      94           0 :       goto reply;
      95             :     }
      96             : 
      97             :   /* socket filename */
      98           0 :   socket_filename = vl_api_from_api_to_new_c_string (&mp->socket_filename);
      99           0 :   if (mp->is_add && socket_id == (u32) ~0)
     100           0 :     socket_id = memif_get_unused_socket_id ();
     101             : 
     102           0 :   rv = vnet_get_api_error_and_free (
     103           0 :     memif_socket_filename_add_del (mp->is_add, socket_id, socket_filename));
     104             : 
     105           0 :   vec_free (socket_filename);
     106             : 
     107           0 : reply:
     108           0 :   REPLY_MACRO2 (VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_V2_REPLY,
     109             :                 ({ rmp->socket_id = htonl (socket_id); }));
     110             : }
     111             : 
     112             : /**
     113             :  * @brief Message handler for memif_create API.
     114             :  * @param mp vl_api_memif_create_t * mp the api message
     115             :  */
     116             : void
     117          22 : vl_api_memif_create_t_handler (vl_api_memif_create_t * mp)
     118             : {
     119          22 :   memif_main_t *mm = &memif_main;
     120          22 :   vlib_main_t *vm = vlib_get_main ();
     121             :   vl_api_memif_create_reply_t *rmp;
     122          22 :   memif_create_if_args_t args = { 0 };
     123          22 :   u32 ring_size = MEMIF_DEFAULT_RING_SIZE;
     124             :   static const u8 empty_hw_addr[6];
     125          22 :   int rv = 0;
     126             :   mac_address_t mac;
     127             : 
     128             :   /* id */
     129          22 :   args.id = clib_net_to_host_u32 (mp->id);
     130             : 
     131             :   /* socket-id */
     132          22 :   args.socket_id = clib_net_to_host_u32 (mp->socket_id);
     133             : 
     134             :   /* secret */
     135          22 :   mp->secret[ARRAY_LEN (mp->secret) - 1] = 0;
     136          22 :   if (strlen ((char *) mp->secret) > 0)
     137             :     {
     138           6 :       vec_validate (args.secret, strlen ((char *) mp->secret));
     139           6 :       strncpy ((char *) args.secret, (char *) mp->secret,
     140           6 :                vec_len (args.secret));
     141             :     }
     142             : 
     143             :   /* role */
     144          22 :   args.is_master = (ntohl (mp->role) == MEMIF_ROLE_API_MASTER);
     145             : 
     146             :   /* mode */
     147          22 :   args.mode = ntohl (mp->mode);
     148             : 
     149          22 :   args.is_zero_copy = mp->no_zero_copy ? 0 : 1;
     150             : 
     151             :   /* rx/tx queues */
     152          22 :   if (args.is_master == 0)
     153             :     {
     154          11 :       args.rx_queues = MEMIF_DEFAULT_RX_QUEUES;
     155          11 :       args.tx_queues = MEMIF_DEFAULT_TX_QUEUES;
     156          11 :       if (mp->rx_queues)
     157             :         {
     158           0 :           args.rx_queues = mp->rx_queues;
     159             :         }
     160          11 :       if (mp->tx_queues)
     161             :         {
     162           0 :           args.tx_queues = mp->tx_queues;
     163             :         }
     164             :     }
     165             : 
     166             :   /* ring size */
     167          22 :   if (mp->ring_size)
     168             :     {
     169           6 :       ring_size = ntohl (mp->ring_size);
     170             :     }
     171          22 :   if (!is_pow2 (ring_size))
     172             :     {
     173           0 :       rv = VNET_API_ERROR_INVALID_ARGUMENT;
     174           0 :       goto reply;
     175             :     }
     176          22 :   args.log2_ring_size = min_log2 (ring_size);
     177             : 
     178             :   /* buffer size */
     179          22 :   args.buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
     180          22 :   if (mp->buffer_size)
     181             :     {
     182           6 :       args.buffer_size = ntohs (mp->buffer_size);
     183             :     }
     184             : 
     185             :   /* MAC address */
     186          22 :   mac_address_decode (mp->hw_addr, &mac);
     187          22 :   if (memcmp (&mac, empty_hw_addr, 6) != 0)
     188             :     {
     189           0 :       memcpy (args.hw_addr, &mac, 6);
     190           0 :       args.hw_addr_set = 1;
     191             :     }
     192             : 
     193          22 :   rv = vnet_get_api_error_and_free (memif_create_if (vm, &args));
     194             : 
     195          22 :   vec_free (args.secret);
     196             : 
     197          22 : reply:
     198             :   /* *INDENT-OFF* */
     199          22 :   REPLY_MACRO2 (VL_API_MEMIF_CREATE_REPLY,
     200             :     ({
     201             :       rmp->sw_if_index = htonl (args.sw_if_index);
     202             :     }));
     203             :   /* *INDENT-ON* */
     204             : }
     205             : 
     206             : /**
     207             :  * @brief Message handler for memif_create_v2 API.
     208             :  * @param mp vl_api_memif_create_v2_t * mp the api message
     209             :  */
     210             : void
     211           0 : vl_api_memif_create_v2_t_handler (vl_api_memif_create_v2_t *mp)
     212             : {
     213           0 :   memif_main_t *mm = &memif_main;
     214           0 :   vlib_main_t *vm = vlib_get_main ();
     215             :   vl_api_memif_create_reply_t *rmp;
     216           0 :   memif_create_if_args_t args = { 0 };
     217           0 :   u32 ring_size = MEMIF_DEFAULT_RING_SIZE;
     218             :   static const u8 empty_hw_addr[6];
     219           0 :   int rv = 0;
     220             :   mac_address_t mac;
     221             : 
     222             :   /* id */
     223           0 :   args.id = clib_net_to_host_u32 (mp->id);
     224             : 
     225             :   /* socket-id */
     226           0 :   args.socket_id = clib_net_to_host_u32 (mp->socket_id);
     227             : 
     228             :   /* secret */
     229           0 :   mp->secret[ARRAY_LEN (mp->secret) - 1] = 0;
     230           0 :   if (strlen ((char *) mp->secret) > 0)
     231             :     {
     232           0 :       vec_validate (args.secret, strlen ((char *) mp->secret));
     233           0 :       strncpy ((char *) args.secret, (char *) mp->secret,
     234           0 :                vec_len (args.secret));
     235             :     }
     236             : 
     237             :   /* role */
     238           0 :   args.is_master = (ntohl (mp->role) == MEMIF_ROLE_API_MASTER);
     239             : 
     240             :   /* mode */
     241           0 :   args.mode = ntohl (mp->mode);
     242             : 
     243           0 :   args.is_zero_copy = mp->no_zero_copy ? 0 : 1;
     244             : 
     245           0 :   args.use_dma = mp->use_dma;
     246             : 
     247             :   /* rx/tx queues */
     248           0 :   if (args.is_master == 0)
     249             :     {
     250           0 :       args.rx_queues = MEMIF_DEFAULT_RX_QUEUES;
     251           0 :       args.tx_queues = MEMIF_DEFAULT_TX_QUEUES;
     252           0 :       if (mp->rx_queues)
     253             :         {
     254           0 :           args.rx_queues = mp->rx_queues;
     255             :         }
     256           0 :       if (mp->tx_queues)
     257             :         {
     258           0 :           args.tx_queues = mp->tx_queues;
     259             :         }
     260             :     }
     261             : 
     262             :   /* ring size */
     263           0 :   if (mp->ring_size)
     264             :     {
     265           0 :       ring_size = ntohl (mp->ring_size);
     266             :     }
     267           0 :   if (!is_pow2 (ring_size))
     268             :     {
     269           0 :       rv = VNET_API_ERROR_INVALID_ARGUMENT;
     270           0 :       goto reply;
     271             :     }
     272           0 :   args.log2_ring_size = min_log2 (ring_size);
     273             : 
     274             :   /* buffer size */
     275           0 :   args.buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
     276           0 :   if (mp->buffer_size)
     277             :     {
     278           0 :       args.buffer_size = ntohs (mp->buffer_size);
     279             :     }
     280             : 
     281             :   /* MAC address */
     282           0 :   mac_address_decode (mp->hw_addr, &mac);
     283           0 :   if (memcmp (&mac, empty_hw_addr, 6) != 0)
     284             :     {
     285           0 :       memcpy (args.hw_addr, &mac, 6);
     286           0 :       args.hw_addr_set = 1;
     287             :     }
     288             : 
     289           0 :   rv = vnet_api_error (memif_create_if (vm, &args));
     290             : 
     291           0 :   vec_free (args.secret);
     292             : 
     293           0 : reply:
     294           0 :   REPLY_MACRO2 (VL_API_MEMIF_CREATE_V2_REPLY,
     295             :                 ({ rmp->sw_if_index = htonl (args.sw_if_index); }));
     296             : }
     297             : 
     298             : /**
     299             :  * @brief Message handler for memif_delete API.
     300             :  * @param mp vl_api_memif_delete_t * mp the api message
     301             :  */
     302             : void
     303          16 : vl_api_memif_delete_t_handler (vl_api_memif_delete_t * mp)
     304             : {
     305          16 :   memif_main_t *mm = &memif_main;
     306          16 :   vlib_main_t *vm = vlib_get_main ();
     307          16 :   vnet_main_t *vnm = vnet_get_main ();
     308             :   vl_api_memif_delete_reply_t *rmp;
     309             :   vnet_hw_interface_t *hi;
     310             :   memif_if_t *mif;
     311          16 :   int rv = 0;
     312             : 
     313             :   hi =
     314          16 :     vnet_get_sup_hw_interface_api_visible_or_null (vnm,
     315             :                                                    ntohl (mp->sw_if_index));
     316             : 
     317          16 :   if (hi == NULL || memif_device_class.index != hi->dev_class_index)
     318           0 :     rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
     319             :   else
     320             :     {
     321          16 :       mif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
     322          16 :       rv = vnet_get_api_error_and_free (memif_delete_if (vm, mif));
     323             :     }
     324             : 
     325          16 :   REPLY_MACRO (VL_API_MEMIF_DELETE_REPLY);
     326             : }
     327             : 
     328             : static void
     329          51 : send_memif_details (vl_api_registration_t * reg,
     330             :                     memif_if_t * mif,
     331             :                     vnet_sw_interface_t * swif,
     332             :                     u8 * interface_name, u32 context)
     333             : {
     334             :   vl_api_memif_details_t *mp;
     335          51 :   vnet_main_t *vnm = vnet_get_main ();
     336          51 :   memif_main_t *mm = &memif_main;
     337             :   vnet_hw_interface_t *hwif;
     338             :   memif_socket_file_t *msf;
     339             : 
     340          51 :   hwif = vnet_get_sup_hw_interface (vnm, swif->sw_if_index);
     341             : 
     342          51 :   mp = vl_msg_api_alloc (sizeof (*mp));
     343          51 :   clib_memset (mp, 0, sizeof (*mp));
     344             : 
     345          51 :   mp->_vl_msg_id = htons (VL_API_MEMIF_DETAILS + mm->msg_id_base);
     346          51 :   mp->context = context;
     347             : 
     348          51 :   mp->sw_if_index = htonl (swif->sw_if_index);
     349          51 :   strncpy ((char *) mp->if_name,
     350             :            (char *) interface_name, ARRAY_LEN (mp->if_name) - 1);
     351             : 
     352          51 :   if (hwif->hw_address)
     353             :     {
     354          51 :       mac_address_encode ((mac_address_t *) hwif->hw_address, mp->hw_addr);
     355             :     }
     356             : 
     357          51 :   mp->id = clib_host_to_net_u32 (mif->id);
     358             : 
     359          51 :   msf = pool_elt_at_index (mm->socket_files, mif->socket_file_index);
     360          51 :   mp->socket_id = clib_host_to_net_u32 (msf->socket_id);
     361             : 
     362          51 :   mp->role =
     363          51 :     (mif->flags & MEMIF_IF_FLAG_IS_SLAVE) ? MEMIF_ROLE_API_SLAVE :
     364             :     MEMIF_ROLE_API_MASTER;
     365          51 :   mp->role = htonl (mp->role);
     366          51 :   mp->mode = htonl (mif->mode);
     367          51 :   mp->ring_size = htonl (1 << mif->run.log2_ring_size);
     368          51 :   mp->buffer_size = htons (mif->run.buffer_size);
     369          51 :   mp->zero_copy = (mif->flags & MEMIF_IF_FLAG_ZERO_COPY) ? 1 : 0;
     370             : 
     371          51 :   mp->flags = 0;
     372          51 :   mp->flags |= (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
     373          51 :     IF_STATUS_API_FLAG_ADMIN_UP : 0;
     374          51 :   mp->flags |= (hwif->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
     375          51 :     IF_STATUS_API_FLAG_LINK_UP : 0;
     376          51 :   mp->flags = htonl (mp->flags);
     377             : 
     378             : 
     379          51 :   vl_api_send_msg (reg, (u8 *) mp);
     380          51 : }
     381             : 
     382             : /**
     383             :  * @brief Message handler for memif_dump API.
     384             :  * @param mp vl_api_memif_dump_t * mp the api message
     385             :  */
     386             : void
     387          44 : vl_api_memif_dump_t_handler (vl_api_memif_dump_t * mp)
     388             : {
     389          44 :   memif_main_t *mm = &memif_main;
     390          44 :   vnet_main_t *vnm = vnet_get_main ();
     391             :   vnet_sw_interface_t *swif;
     392             :   memif_if_t *mif;
     393          44 :   u8 *if_name = 0;
     394             :   vl_api_registration_t *reg;
     395             : 
     396          44 :   reg = vl_api_client_index_to_registration (mp->client_index);
     397          44 :   if (!reg)
     398           0 :     return;
     399             : 
     400             :   /* *INDENT-OFF* */
     401          95 :   pool_foreach (mif, mm->interfaces)
     402             :      {
     403          51 :       swif = vnet_get_sw_interface (vnm, mif->sw_if_index);
     404             : 
     405          51 :       if_name = format (if_name, "%U%c",
     406             :                         format_vnet_sw_interface_name,
     407             :                         vnm, swif, 0);
     408             : 
     409          51 :       send_memif_details (reg, mif, swif, if_name, mp->context);
     410          51 :       vec_set_len (if_name, 0);
     411             :     }
     412             :   /* *INDENT-ON* */
     413             : 
     414          44 :   vec_free (if_name);
     415             : }
     416             : 
     417             : static void
     418          28 : send_memif_socket_filename_details (vl_api_registration_t * reg,
     419             :                                     u32 socket_id,
     420             :                                     u8 * socket_filename, u32 context)
     421             : {
     422             :   vl_api_memif_socket_filename_details_t *mp;
     423          28 :   memif_main_t *mm = &memif_main;
     424             : 
     425          28 :   mp = vl_msg_api_alloc (sizeof (*mp));
     426          28 :   clib_memset (mp, 0, sizeof (*mp));
     427             : 
     428          28 :   mp->_vl_msg_id = htons (VL_API_MEMIF_SOCKET_FILENAME_DETAILS
     429          28 :                           + mm->msg_id_base);
     430          28 :   mp->context = context;
     431             : 
     432          28 :   mp->socket_id = clib_host_to_net_u32 (socket_id);
     433          28 :   strncpy ((char *) mp->socket_filename,
     434             :            (char *) socket_filename, ARRAY_LEN (mp->socket_filename) - 1);
     435             : 
     436          28 :   vl_api_send_msg (reg, (u8 *) mp);
     437          28 : }
     438             : 
     439             : /**
     440             :  * @brief Message handler for memif_socket_filename_dump API.
     441             :  * @param mp vl_api_memif_socket_filename_dump_t api message
     442             :  */
     443             : void
     444          17 :   vl_api_memif_socket_filename_dump_t_handler
     445             :   (vl_api_memif_socket_filename_dump_t * mp)
     446             : {
     447          17 :   memif_main_t *mm = &memif_main;
     448             :   vl_api_registration_t *reg;
     449             :   u32 sock_id;
     450             :   u32 msf_idx;
     451             : 
     452          17 :   reg = vl_api_client_index_to_registration (mp->client_index);
     453          17 :   if (!reg)
     454           0 :     return;
     455             : 
     456             :   /* *INDENT-OFF* */
     457        1133 :   hash_foreach (sock_id, msf_idx, mm->socket_file_index_by_sock_id,
     458             :     ({
     459             :       memif_socket_file_t *msf;
     460             :       u8 *filename;
     461             : 
     462             :       msf = pool_elt_at_index(mm->socket_files, msf_idx);
     463             :       filename = msf->filename;
     464             :       send_memif_socket_filename_details(reg, sock_id, filename, mp->context);
     465             :     }));
     466             :   /* *INDENT-ON* */
     467             : }
     468             : 
     469             : /* Set up the API message handling tables */
     470             : #include <memif/memif.api.c>
     471             : clib_error_t *
     472         575 : memif_plugin_api_hookup (vlib_main_t * vm)
     473             : {
     474         575 :   memif_main_t *mm = &memif_main;
     475             : 
     476             :   /* Ask for a correctly-sized block of API message decode slots */
     477         575 :   mm->msg_id_base = setup_message_id_table ();
     478         575 :   return 0;
     479             : }
     480             : 
     481             : /*
     482             :  * fd.io coding-style-patch-verification: ON
     483             :  *
     484             :  * Local Variables:
     485             :  * eval: (c-set-style "gnu")
     486             :  * End:
     487             :  */

Generated by: LCOV version 1.14