LCOV - code coverage report
Current view: top level - vnet/devices/virtio - virtio.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 133 334 39.8 %
Date: 2023-07-05 22:20:52 Functions: 12 15 80.0 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * Copyright (c) 2017 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             : 
      18             : #include <sys/types.h>
      19             : #include <sys/stat.h>
      20             : #include <fcntl.h>
      21             : #include <net/if.h>
      22             : #include <linux/if_tun.h>
      23             : #include <sys/ioctl.h>
      24             : #include <sys/eventfd.h>
      25             : 
      26             : #include <vlib/vlib.h>
      27             : #include <vlib/pci/pci.h>
      28             : #include <vlib/unix/unix.h>
      29             : #include <vnet/ethernet/ethernet.h>
      30             : #include <vnet/ip/ip4_packet.h>
      31             : #include <vnet/ip/ip6_packet.h>
      32             : #include <vnet/devices/virtio/virtio.h>
      33             : #include <vnet/devices/virtio/virtio_inline.h>
      34             : #include <vnet/devices/virtio/pci.h>
      35             : #include <vnet/interface/rx_queue_funcs.h>
      36             : #include <vnet/interface/tx_queue_funcs.h>
      37             : 
      38             : virtio_main_t virtio_main;
      39             : 
      40             : #define _IOCTL(fd,a,...) \
      41             :   if (ioctl (fd, a, __VA_ARGS__) < 0) \
      42             :     { \
      43             :       err = clib_error_return_unix (0, "ioctl(" #a ")"); \
      44             :       goto error; \
      45             :     }
      46             : 
      47             : static clib_error_t *
      48           0 : call_read_ready (clib_file_t * uf)
      49             : {
      50           0 :   vnet_main_t *vnm = vnet_get_main ();
      51             :   u64 b;
      52             : 
      53           0 :   CLIB_UNUSED (ssize_t size) = read (uf->file_descriptor, &b, sizeof (b));
      54           0 :   vnet_hw_if_rx_queue_set_int_pending (vnm, uf->private_data);
      55             : 
      56           0 :   return 0;
      57             : }
      58             : 
      59             : 
      60             : clib_error_t *
      61         600 : virtio_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 idx, u16 sz)
      62             : {
      63             :   vnet_virtio_vring_t *vring;
      64             :   int i;
      65             : 
      66         600 :   if (!is_pow2 (sz))
      67           0 :     return clib_error_return (0, "ring size must be power of 2");
      68             : 
      69         600 :   if (sz > 32768)
      70           0 :     return clib_error_return (0, "ring size must be 32768 or lower");
      71             : 
      72         600 :   if (sz == 0)
      73           0 :     sz = 256;
      74             : 
      75         600 :   if (idx % 2)
      76             :     {
      77         300 :       vec_validate_aligned (vif->txq_vrings, TX_QUEUE_ACCESS (idx),
      78             :                             CLIB_CACHE_LINE_BYTES);
      79         300 :       vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
      80         300 :       clib_spinlock_init (&vring->lockp);
      81             :     }
      82             :   else
      83             :     {
      84         300 :       vec_validate_aligned (vif->rxq_vrings, RX_QUEUE_ACCESS (idx),
      85             :                             CLIB_CACHE_LINE_BYTES);
      86         300 :       vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
      87             :     }
      88         600 :   i = sizeof (vnet_virtio_vring_desc_t) * sz;
      89         600 :   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
      90         600 :   vring->desc = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
      91         600 :   clib_memset (vring->desc, 0, i);
      92             : 
      93         600 :   i = sizeof (vnet_virtio_vring_avail_t) + sz * sizeof (vring->avail->ring[0]);
      94         600 :   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
      95         600 :   vring->avail = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
      96         600 :   clib_memset (vring->avail, 0, i);
      97             :   // tell kernel that we don't need interrupt
      98         600 :   vring->avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
      99             : 
     100         600 :   i = sizeof (vnet_virtio_vring_used_t) +
     101         600 :       sz * sizeof (vnet_virtio_vring_used_elem_t);
     102         600 :   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
     103         600 :   vring->used = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
     104         600 :   clib_memset (vring->used, 0, i);
     105             : 
     106         600 :   vring->queue_id = idx;
     107         600 :   ASSERT (vring->buffers == 0);
     108         600 :   vec_validate_aligned (vring->buffers, sz, CLIB_CACHE_LINE_BYTES);
     109             : 
     110         600 :   if (idx & 1)
     111             :     {
     112         300 :       clib_memset_u32 (vring->buffers, ~0, sz);
     113             :       // tx path: suppress the interrupts from kernel
     114         300 :       vring->call_fd = -1;
     115             :     }
     116             :   else
     117         300 :     vring->call_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
     118             : 
     119         600 :   vring->total_packets = 0;
     120         600 :   vring->queue_size = sz;
     121         600 :   vring->kick_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
     122         600 :   virtio_log_debug (vif, "vring %u size %u call_fd %d kick_fd %d", idx,
     123             :                     vring->queue_size, vring->call_fd, vring->kick_fd);
     124             : 
     125         600 :   return 0;
     126             : }
     127             : 
     128             : inline void
     129         600 : virtio_free_buffers (vlib_main_t *vm, vnet_virtio_vring_t *vring)
     130             : {
     131         600 :   u16 used = vring->desc_in_use;
     132         600 :   u16 last = vring->last_used_idx;
     133         600 :   u16 mask = vring->queue_size - 1;
     134             : 
     135       74231 :   while (used)
     136             :     {
     137       73631 :       vlib_buffer_free (vm, &vring->buffers[last & mask], 1);
     138       73631 :       last++;
     139       73631 :       used--;
     140             :     }
     141         600 : }
     142             : 
     143             : clib_error_t *
     144         300 : virtio_vring_free_rx (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
     145             : {
     146         300 :   vnet_virtio_vring_t *vring =
     147         300 :     vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
     148             : 
     149         300 :   clib_file_del_by_index (&file_main, vring->call_file_index);
     150         300 :   close (vring->kick_fd);
     151         300 :   close (vring->call_fd);
     152         300 :   if (vring->used)
     153             :     {
     154         300 :       virtio_free_buffers (vm, vring);
     155         300 :       clib_mem_free (vring->used);
     156             :     }
     157         300 :   if (vring->desc)
     158         300 :     clib_mem_free (vring->desc);
     159         300 :   if (vring->avail)
     160         300 :     clib_mem_free (vring->avail);
     161         300 :   vec_free (vring->buffers);
     162         300 :   return 0;
     163             : }
     164             : 
     165             : clib_error_t *
     166         300 : virtio_vring_free_tx (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
     167             : {
     168         300 :   vnet_virtio_vring_t *vring =
     169         300 :     vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
     170             : 
     171         300 :   close (vring->kick_fd);
     172         300 :   if (vring->used)
     173             :     {
     174         300 :       virtio_free_buffers (vm, vring);
     175         300 :       clib_mem_free (vring->used);
     176             :     }
     177         300 :   if (vring->desc)
     178         300 :     clib_mem_free (vring->desc);
     179         300 :   if (vring->avail)
     180         300 :     clib_mem_free (vring->avail);
     181         300 :   vec_free (vring->buffers);
     182         300 :   gro_flow_table_free (vring->flow_table);
     183         300 :   virtio_vring_buffering_free (vm, vring->buffering);
     184         300 :   clib_spinlock_free (&vring->lockp);
     185         300 :   return 0;
     186             : }
     187             : 
     188             : void
     189         108 : virtio_set_packet_coalesce (virtio_if_t * vif)
     190             : {
     191         108 :   vnet_main_t *vnm = vnet_get_main ();
     192         108 :   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
     193             :   vnet_virtio_vring_t *vring;
     194         108 :   vif->packet_coalesce = 1;
     195         216 :   vec_foreach (vring, vif->txq_vrings)
     196             :   {
     197         108 :     gro_flow_table_init (&vring->flow_table,
     198         108 :                          vif->type & (VIRTIO_IF_TYPE_TAP |
     199             :                                       VIRTIO_IF_TYPE_PCI), hw->tx_node_index);
     200             :   }
     201         108 : }
     202             : 
     203             : clib_error_t *
     204           0 : virtio_set_packet_buffering (virtio_if_t * vif, u16 buffering_size)
     205             : {
     206           0 :   vnet_main_t *vnm = vnet_get_main ();
     207           0 :   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
     208             :   vnet_virtio_vring_t *vring;
     209           0 :   clib_error_t *error = 0;
     210             : 
     211           0 :   vec_foreach (vring, vif->txq_vrings)
     212             :   {
     213           0 :     if ((error =
     214           0 :          virtio_vring_buffering_init (&vring->buffering, hw->tx_node_index,
     215             :                                       buffering_size)))
     216             :       {
     217           0 :         break;
     218             :       }
     219             :   }
     220             : 
     221           0 :   return error;
     222             : }
     223             : 
     224             : static void
     225         300 : virtio_vring_fill (vlib_main_t *vm, virtio_if_t *vif,
     226             :                    vnet_virtio_vring_t *vring)
     227             : {
     228         300 :   if (vif->is_packed)
     229           0 :     virtio_refill_vring_packed (vm, vif, vif->type, vring,
     230           0 :                                 vif->virtio_net_hdr_sz,
     231             :                                 virtio_input_node.index);
     232             :   else
     233         300 :     virtio_refill_vring_split (vm, vif, vif->type, vring,
     234         300 :                                vif->virtio_net_hdr_sz,
     235             :                                virtio_input_node.index);
     236         300 : }
     237             : 
     238             : void
     239         300 : virtio_vring_set_rx_queues (vlib_main_t *vm, virtio_if_t *vif)
     240             : {
     241         300 :   vnet_main_t *vnm = vnet_get_main ();
     242             :   vnet_virtio_vring_t *vring;
     243         300 :   u32 i = 0;
     244             : 
     245         300 :   vnet_hw_if_set_input_node (vnm, vif->hw_if_index, virtio_input_node.index);
     246             : 
     247         600 :   vec_foreach (vring, vif->rxq_vrings)
     248             :     {
     249         600 :       vring->queue_index = vnet_hw_if_register_rx_queue (
     250         300 :         vnm, vif->hw_if_index, RX_QUEUE_ACCESS (vring->queue_id),
     251             :         VNET_HW_IF_RXQ_THREAD_ANY);
     252         300 :       vring->buffer_pool_index = vlib_buffer_pool_get_default_for_numa (
     253         300 :         vm, vnet_hw_if_get_rx_queue_numa_node (vnm, vring->queue_index));
     254         300 :       if (vif->type == VIRTIO_IF_TYPE_TAP || vif->type == VIRTIO_IF_TYPE_TUN)
     255         300 :         {
     256             : 
     257         600 :           clib_file_t f = {
     258             :             .read_function = call_read_ready,
     259             :             .flags = UNIX_FILE_EVENT_EDGE_TRIGGERED,
     260         300 :             .file_descriptor = vring->call_fd,
     261         300 :             .private_data = vring->queue_index,
     262         300 :             .description = format (0, "%U vring %u", format_virtio_device_name,
     263         300 :                                    vif->dev_instance, vring->queue_id),
     264             :           };
     265             : 
     266         300 :           vring->call_file_index = clib_file_add (&file_main, &f);
     267         300 :           vnet_hw_if_set_rx_queue_file_index (vnm, vring->queue_index,
     268             :                                               vring->call_file_index);
     269             :         }
     270           0 :       else if ((vif->type == VIRTIO_IF_TYPE_PCI) && (vif->support_int_mode) &&
     271           0 :                (vif->msix_enabled == VIRTIO_MSIX_ENABLED))
     272             :         {
     273             :           u32 file_index;
     274           0 :           file_index =
     275           0 :             vlib_pci_get_msix_file_index (vm, vif->pci_dev_handle, i + 1);
     276           0 :           vnet_hw_if_set_rx_queue_file_index (vnm, vring->queue_index,
     277             :                                               file_index);
     278           0 :           i++;
     279             :         }
     280         300 :       vnet_hw_if_set_rx_queue_mode (vnm, vring->queue_index,
     281             :                                     VNET_HW_IF_RX_MODE_POLLING);
     282         300 :       vring->mode = VNET_HW_IF_RX_MODE_POLLING;
     283         300 :       virtio_vring_fill (vm, vif, vring);
     284             :     }
     285         300 :   vnet_hw_if_update_runtime_data (vnm, vif->hw_if_index);
     286         300 : }
     287             : 
     288             : void
     289         300 : virtio_vring_set_tx_queues (vlib_main_t *vm, virtio_if_t *vif)
     290             : {
     291         300 :   vnet_main_t *vnm = vnet_get_main ();
     292             :   vnet_virtio_vring_t *vring;
     293             : 
     294         600 :   vec_foreach (vring, vif->txq_vrings)
     295             :     {
     296         300 :       vring->queue_index = vnet_hw_if_register_tx_queue (
     297         300 :         vnm, vif->hw_if_index, TX_QUEUE_ACCESS (vring->queue_id));
     298             :     }
     299             : 
     300         300 :   if (vif->num_txqs == 0)
     301             :     {
     302           0 :       virtio_log_error (vif, "Interface %U has 0 txq",
     303             :                         format_vnet_hw_if_index_name, vnm, vif->hw_if_index);
     304           0 :       return;
     305             :     }
     306             : 
     307         600 :   for (u32 j = 0; j < vlib_get_n_threads (); j++)
     308             :     {
     309         300 :       u32 qi = vif->txq_vrings[j % vif->num_txqs].queue_index;
     310         300 :       vnet_hw_if_tx_queue_assign_thread (vnm, qi, j);
     311             :     }
     312             : 
     313         300 :   vnet_hw_if_update_runtime_data (vnm, vif->hw_if_index);
     314             : }
     315             : 
     316             : inline void
     317         300 : virtio_set_net_hdr_size (virtio_if_t * vif)
     318             : {
     319         300 :   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) ||
     320           0 :       vif->features & VIRTIO_FEATURE (VIRTIO_F_VERSION_1))
     321         300 :     vif->virtio_net_hdr_sz = sizeof (vnet_virtio_net_hdr_v1_t);
     322             :   else
     323           0 :     vif->virtio_net_hdr_sz = sizeof (vnet_virtio_net_hdr_t);
     324         300 : }
     325             : 
     326             : inline void
     327           0 : virtio_show (vlib_main_t *vm, u32 *hw_if_indices, u8 show_descr,
     328             :              virtio_if_type_t type)
     329             : {
     330             :   u32 i, j, hw_if_index;
     331             :   virtio_if_t *vif;
     332           0 :   vnet_main_t *vnm = &vnet_main;
     333           0 :   virtio_main_t *mm = &virtio_main;
     334             :   vnet_virtio_vring_t *vring;
     335             :   struct feat_struct
     336             :   {
     337             :     u8 bit;
     338             :     char *str;
     339             :   };
     340             :   struct feat_struct *feat_entry;
     341             : 
     342             :   static struct feat_struct feat_array[] = {
     343             : #define _(s,b) { .str = #s, .bit = b, },
     344             :     foreach_virtio_net_features
     345             : #undef _
     346             :     {.str = NULL}
     347             :   };
     348             : 
     349             :   struct feat_struct *flag_entry;
     350             :   static struct feat_struct flags_array[] = {
     351             : #define _(b,e,s) { .bit = b, .str = s, },
     352             :     foreach_virtio_if_flag
     353             : #undef _
     354             :     {.str = NULL}
     355             :   };
     356             : 
     357           0 :   if (!hw_if_indices)
     358           0 :     return;
     359             : 
     360           0 :   for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
     361             :     {
     362             :       vnet_hw_interface_t *hi =
     363           0 :         vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
     364           0 :       vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
     365           0 :       if (vif->type != type)
     366           0 :         continue;
     367           0 :       vlib_cli_output (vm, "Interface: %U (ifindex %d)",
     368             :                        format_vnet_hw_if_index_name, vnm,
     369           0 :                        hw_if_indices[hw_if_index], vif->hw_if_index);
     370           0 :       if (type == VIRTIO_IF_TYPE_PCI)
     371             :         {
     372           0 :           vlib_cli_output (vm, "  PCI Address: %U", format_vlib_pci_addr,
     373             :                            &vif->pci_addr);
     374             :         }
     375           0 :       if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
     376             :         {
     377           0 :           u8 *str = 0;
     378           0 :           if (vif->host_if_name)
     379           0 :             vlib_cli_output (vm, "  name \"%s\"", vif->host_if_name);
     380           0 :           if (vif->net_ns)
     381           0 :             vlib_cli_output (vm, "  host-ns \"%s\"", vif->net_ns);
     382           0 :           if (vif->host_mtu_size)
     383           0 :             vlib_cli_output (vm, "  host-mtu-size \"%d\"",
     384             :                              vif->host_mtu_size);
     385           0 :           if (type == VIRTIO_IF_TYPE_TAP)
     386           0 :             vlib_cli_output (vm, "  host-mac-addr: %U",
     387           0 :                              format_ethernet_address, vif->host_mac_addr);
     388           0 :           vlib_cli_output (vm, "  host-carrier-up: %u", vif->host_carrier_up);
     389             : 
     390           0 :           vec_foreach_index (i, vif->vhost_fds)
     391           0 :             str = format (str, " %d", vif->vhost_fds[i]);
     392           0 :           vlib_cli_output (vm, "  vhost-fds%v", str);
     393           0 :           vec_free (str);
     394           0 :           vec_foreach_index (i, vif->tap_fds)
     395           0 :             str = format (str, " %d", vif->tap_fds[i]);
     396           0 :           vlib_cli_output (vm, "  tap-fds%v", str);
     397           0 :           vec_free (str);
     398             :         }
     399           0 :       vlib_cli_output (vm, "  gso-enabled %d", vif->gso_enabled);
     400           0 :       vlib_cli_output (vm, "  csum-enabled %d", vif->csum_offload_enabled);
     401           0 :       vlib_cli_output (vm, "  packet-coalesce %d", vif->packet_coalesce);
     402           0 :       vlib_cli_output (vm, "  packet-buffering %d", vif->packet_buffering);
     403           0 :       if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_PCI))
     404           0 :         vlib_cli_output (vm, "  Mac Address: %U", format_ethernet_address,
     405           0 :                          vif->mac_addr);
     406           0 :       vlib_cli_output (vm, "  Device instance: %u", vif->dev_instance);
     407           0 :       vlib_cli_output (vm, "  flags 0x%x", vif->flags);
     408           0 :       flag_entry = (struct feat_struct *) &flags_array;
     409           0 :       while (flag_entry->str)
     410             :         {
     411           0 :           if (vif->flags & (1ULL << flag_entry->bit))
     412           0 :             vlib_cli_output (vm, "    %s (%d)", flag_entry->str,
     413           0 :                              flag_entry->bit);
     414           0 :           flag_entry++;
     415             :         }
     416           0 :       if (type == VIRTIO_IF_TYPE_PCI)
     417             :         {
     418           0 :           device_status (vm, vif);
     419             :         }
     420           0 :       vlib_cli_output (vm, "  features 0x%lx", vif->features);
     421           0 :       feat_entry = (struct feat_struct *) &feat_array;
     422           0 :       while (feat_entry->str)
     423             :         {
     424           0 :           if (vif->features & (1ULL << feat_entry->bit))
     425           0 :             vlib_cli_output (vm, "    %s (%d)", feat_entry->str,
     426           0 :                              feat_entry->bit);
     427           0 :           feat_entry++;
     428             :         }
     429           0 :       vlib_cli_output (vm, "  remote-features 0x%lx", vif->remote_features);
     430           0 :       feat_entry = (struct feat_struct *) &feat_array;
     431           0 :       while (feat_entry->str)
     432             :         {
     433           0 :           if (vif->remote_features & (1ULL << feat_entry->bit))
     434           0 :             vlib_cli_output (vm, "    %s (%d)", feat_entry->str,
     435           0 :                              feat_entry->bit);
     436           0 :           feat_entry++;
     437             :         }
     438           0 :       vlib_cli_output (vm, "  Number of RX Virtqueue  %u", vif->num_rxqs);
     439           0 :       vlib_cli_output (vm, "  Number of TX Virtqueue  %u", vif->num_txqs);
     440           0 :       if (type == VIRTIO_IF_TYPE_PCI && vif->cxq_vring != NULL &&
     441           0 :           vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
     442           0 :         vlib_cli_output (vm, "  Number of CTRL Virtqueue 1");
     443           0 :       vec_foreach_index (i, vif->rxq_vrings)
     444             :       {
     445           0 :         vring = vec_elt_at_index (vif->rxq_vrings, i);
     446           0 :         vlib_cli_output (vm, "  Virtqueue (RX) %d", vring->queue_id);
     447           0 :         vlib_cli_output (
     448             :           vm, "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
     449           0 :           vring->queue_size, vring->last_used_idx, vring->desc_next,
     450           0 :           vring->desc_in_use);
     451           0 :         if (vif->is_packed)
     452             :           {
     453           0 :             vlib_cli_output (vm,
     454             :                              "    driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
     455           0 :                              vring->driver_event->flags,
     456           0 :                              vring->driver_event->off_wrap,
     457           0 :                              vring->device_event->flags,
     458           0 :                              vring->device_event->off_wrap);
     459           0 :             vlib_cli_output (vm,
     460             :                              "    avail wrap counter %d, used wrap counter %d",
     461           0 :                              vring->avail_wrap_counter,
     462           0 :                              vring->used_wrap_counter);
     463             :           }
     464             :         else
     465           0 :           vlib_cli_output (vm,
     466             :                            "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
     467           0 :                            vring->avail->flags, vring->avail->idx,
     468           0 :                            vring->used->flags, vring->used->idx);
     469           0 :         if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
     470             :           {
     471           0 :             vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
     472             :                              vring->call_fd);
     473             :           }
     474           0 :         if (show_descr)
     475             :           {
     476           0 :             vlib_cli_output (vm, "\n  descriptor table:\n");
     477           0 :             vlib_cli_output (vm,
     478             :                              "   id          addr         len  flags  next/id      user_addr\n");
     479           0 :             vlib_cli_output (vm,
     480             :                              "  ===== ================== ===== ====== ======= ==================\n");
     481           0 :             for (j = 0; j < vring->queue_size; j++)
     482             :               {
     483           0 :                 if (vif->is_packed)
     484             :                   {
     485           0 :                     vnet_virtio_vring_packed_desc_t *desc =
     486           0 :                       &vring->packed_desc[j];
     487           0 :                     vlib_cli_output (vm,
     488             :                                      "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
     489             :                                      j, desc->addr,
     490             :                                      desc->len,
     491           0 :                                      desc->flags, desc->id, desc->addr);
     492             :                   }
     493             :                 else
     494             :                   {
     495           0 :                     vnet_virtio_vring_desc_t *desc = &vring->desc[j];
     496           0 :                     vlib_cli_output (vm,
     497             :                                      "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
     498             :                                      j, desc->addr,
     499             :                                      desc->len,
     500           0 :                                      desc->flags, desc->next, desc->addr);
     501             :                   }
     502             :               }
     503             :           }
     504             :       }
     505           0 :       vec_foreach_index (i, vif->txq_vrings)
     506             :       {
     507           0 :         vring = vec_elt_at_index (vif->txq_vrings, i);
     508           0 :         vlib_cli_output (vm, "  Virtqueue (TX) %d", vring->queue_id);
     509           0 :         vlib_cli_output (
     510             :           vm, "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
     511           0 :           vring->queue_size, vring->last_used_idx, vring->desc_next,
     512           0 :           vring->desc_in_use);
     513           0 :         if (vif->is_packed)
     514             :           {
     515           0 :             vlib_cli_output (vm,
     516             :                              "    driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
     517           0 :                              vring->driver_event->flags,
     518           0 :                              vring->driver_event->off_wrap,
     519           0 :                              vring->device_event->flags,
     520           0 :                              vring->device_event->off_wrap);
     521           0 :             vlib_cli_output (vm,
     522             :                              "    avail wrap counter %d, used wrap counter %d",
     523           0 :                              vring->avail_wrap_counter,
     524           0 :                              vring->used_wrap_counter);
     525             :           }
     526             :         else
     527           0 :           vlib_cli_output (vm,
     528             :                            "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
     529           0 :                            vring->avail->flags, vring->avail->idx,
     530           0 :                            vring->used->flags, vring->used->idx);
     531           0 :         if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
     532             :           {
     533           0 :             vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
     534             :                              vring->call_fd);
     535             :           }
     536           0 :         if (vring->flow_table)
     537             :           {
     538           0 :             vlib_cli_output (vm, "    %U", gro_flow_table_format,
     539             :                              vring->flow_table);
     540             :           }
     541           0 :         if (vif->packet_buffering)
     542             :           {
     543           0 :             vlib_cli_output (vm, "    %U", virtio_vring_buffering_format,
     544             :                              vring->buffering);
     545             :           }
     546           0 :         if (show_descr)
     547             :           {
     548           0 :             vlib_cli_output (vm, "\n  descriptor table:\n");
     549           0 :             vlib_cli_output (vm,
     550             :                              "   id          addr         len  flags  next/id      user_addr\n");
     551           0 :             vlib_cli_output (vm,
     552             :                              "  ===== ================== ===== ====== ======== ==================\n");
     553           0 :             for (j = 0; j < vring->queue_size; j++)
     554             :               {
     555           0 :                 if (vif->is_packed)
     556             :                   {
     557           0 :                     vnet_virtio_vring_packed_desc_t *desc =
     558           0 :                       &vring->packed_desc[j];
     559           0 :                     vlib_cli_output (vm,
     560             :                                      "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
     561             :                                      j, desc->addr,
     562             :                                      desc->len,
     563           0 :                                      desc->flags, desc->id, desc->addr);
     564             :                   }
     565             :                 else
     566             :                   {
     567           0 :                     vnet_virtio_vring_desc_t *desc = &vring->desc[j];
     568           0 :                     vlib_cli_output (vm,
     569             :                                      "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
     570             :                                      j, desc->addr,
     571             :                                      desc->len,
     572           0 :                                      desc->flags, desc->next, desc->addr);
     573             :                   }
     574             :               }
     575             :           }
     576             :       }
     577           0 :       if (type == VIRTIO_IF_TYPE_PCI && vif->cxq_vring != NULL &&
     578           0 :           vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
     579             :         {
     580           0 :           vring = vif->cxq_vring;
     581           0 :           vlib_cli_output (vm, "  Virtqueue (CTRL) %d", vring->queue_id);
     582           0 :           vlib_cli_output (
     583             :             vm, "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
     584           0 :             vring->queue_size, vring->last_used_idx, vring->desc_next,
     585           0 :             vring->desc_in_use);
     586           0 :           if (vif->is_packed)
     587             :             {
     588           0 :               vlib_cli_output (vm,
     589             :                                "    driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
     590           0 :                                vring->driver_event->flags,
     591           0 :                                vring->driver_event->off_wrap,
     592           0 :                                vring->device_event->flags,
     593           0 :                                vring->device_event->off_wrap);
     594           0 :               vlib_cli_output (vm,
     595             :                                "    avail wrap counter %d, used wrap counter %d",
     596           0 :                                vring->avail_wrap_counter,
     597           0 :                                vring->used_wrap_counter);
     598             :             }
     599             :           else
     600             :             {
     601           0 :               vlib_cli_output (vm,
     602             :                                "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
     603           0 :                                vring->avail->flags, vring->avail->idx,
     604           0 :                                vring->used->flags, vring->used->idx);
     605             :             }
     606           0 :           if (show_descr)
     607             :             {
     608           0 :               vlib_cli_output (vm, "\n  descriptor table:\n");
     609           0 :               vlib_cli_output (vm,
     610             :                                "   id          addr         len  flags  next/id      user_addr\n");
     611           0 :               vlib_cli_output (vm,
     612             :                                "  ===== ================== ===== ====== ======== ==================\n");
     613           0 :               for (j = 0; j < vring->queue_size; j++)
     614             :                 {
     615           0 :                   if (vif->is_packed)
     616             :                     {
     617           0 :                       vnet_virtio_vring_packed_desc_t *desc =
     618           0 :                         &vring->packed_desc[j];
     619           0 :                       vlib_cli_output (vm,
     620             :                                        "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
     621             :                                        j, desc->addr,
     622             :                                        desc->len,
     623           0 :                                        desc->flags, desc->id, desc->addr);
     624             :                     }
     625             :                   else
     626             :                     {
     627           0 :                       vnet_virtio_vring_desc_t *desc = &vring->desc[j];
     628           0 :                       vlib_cli_output (vm,
     629             :                                        "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
     630             :                                        j, desc->addr,
     631             :                                        desc->len,
     632           0 :                                        desc->flags, desc->next, desc->addr);
     633             :                     }
     634             :                 }
     635             :             }
     636             :         }
     637             :     }
     638             : 
     639             : }
     640             : 
     641             : static clib_error_t *
     642         559 : virtio_init (vlib_main_t * vm)
     643             : {
     644         559 :   virtio_main_t *vim = &virtio_main;
     645         559 :   clib_error_t *error = 0;
     646             : 
     647         559 :   vim->log_default = vlib_log_register_class ("virtio", 0);
     648         559 :   vlib_log_debug (vim->log_default, "initialized");
     649             : 
     650         559 :   return error;
     651             : }
     652             : 
     653       74479 : VLIB_INIT_FUNCTION (virtio_init);
     654             : 
     655             : /*
     656             :  * fd.io coding-style-patch-verification: ON
     657             :  *
     658             :  * Local Variables:
     659             :  * eval: (c-set-style "gnu")
     660             :  * End:
     661             :  */

Generated by: LCOV version 1.14