LCOV - code coverage report
Current view: top level - vnet/interface - rx_queue.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 91 122 74.6 %
Date: 2023-07-05 22:20:52 Functions: 11 13 84.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2020 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vnet/vnet.h>
      17             : #include <vnet/devices/devices.h>
      18             : #include <vnet/interface/rx_queue_funcs.h>
      19             : #include <vlib/unix/unix.h>
      20             : 
      21         559 : VLIB_REGISTER_LOG_CLASS (if_rxq_log, static) = {
      22             :   .class_name = "interface",
      23             :   .subclass_name = "rx-queue",
      24             : };
      25             : 
      26             : #define log_debug(fmt, ...) vlib_log_debug (if_rxq_log.class, fmt, __VA_ARGS__)
      27             : #define log_err(fmt, ...)   vlib_log_err (if_rxq_log.class, fmt, __VA_ARGS__)
      28             : 
      29             : static u32
      30         570 : next_thread_index (vnet_main_t *vnm, u32 thread_index)
      31             : {
      32         570 :   vnet_device_main_t *vdm = &vnet_device_main;
      33         570 :   if (vdm->first_worker_thread_index == 0)
      34         570 :     return 0;
      35             : 
      36           0 :   if (thread_index != 0 && (thread_index < vdm->first_worker_thread_index ||
      37           0 :                             thread_index > vdm->last_worker_thread_index))
      38             :     {
      39           0 :       thread_index = vdm->next_worker_thread_index++;
      40           0 :       if (vdm->next_worker_thread_index > vdm->last_worker_thread_index)
      41           0 :         vdm->next_worker_thread_index = vdm->first_worker_thread_index;
      42             :     }
      43             : 
      44           0 :   return thread_index;
      45             : }
      46             : 
      47             : static u64
      48        1386 : rx_queue_key (u32 hw_if_index, u32 queue_id)
      49             : {
      50        1386 :   return ((u64) hw_if_index << 32) | queue_id;
      51             : }
      52             : 
      53             : u32
      54         252 : vnet_hw_if_get_rx_queue_index_by_id (vnet_main_t *vnm, u32 hw_if_index,
      55             :                                      u32 queue_id)
      56             : {
      57         252 :   vnet_interface_main_t *im = &vnm->interface_main;
      58         252 :   u64 key = rx_queue_key (hw_if_index, queue_id);
      59         252 :   uword *p = hash_get_mem (im->rxq_index_by_hw_if_index_and_queue_id, &key);
      60         252 :   return p ? p[0] : ~0;
      61             : }
      62             : 
      63             : u32
      64         570 : vnet_hw_if_register_rx_queue (vnet_main_t *vnm, u32 hw_if_index, u32 queue_id,
      65             :                               u32 thread_index)
      66             : {
      67         570 :   vnet_interface_main_t *im = &vnm->interface_main;
      68         570 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
      69             :   vnet_hw_if_rx_queue_t *rxq;
      70         570 :   u64 key = rx_queue_key (hw_if_index, queue_id);
      71             :   u32 queue_index;
      72             : 
      73         570 :   if (hash_get_mem (im->rxq_index_by_hw_if_index_and_queue_id, &key))
      74           0 :     clib_panic ("Trying to register already registered queue id (%u) in the "
      75             :                 "interface %v\n",
      76             :                 queue_id, hi->name);
      77             : 
      78         570 :   thread_index = next_thread_index (vnm, thread_index);
      79             : 
      80         570 :   pool_get_zero (im->hw_if_rx_queues, rxq);
      81         570 :   queue_index = rxq - im->hw_if_rx_queues;
      82         570 :   vec_add1 (hi->rx_queue_indices, queue_index);
      83         570 :   hash_set_mem_alloc (&im->rxq_index_by_hw_if_index_and_queue_id, &key,
      84             :                       queue_index);
      85         570 :   rxq->hw_if_index = hw_if_index;
      86         570 :   rxq->dev_instance = hi->dev_instance;
      87         570 :   rxq->queue_id = queue_id;
      88         570 :   rxq->thread_index = thread_index;
      89         570 :   rxq->mode = VNET_HW_IF_RX_MODE_POLLING;
      90         570 :   rxq->file_index = ~0;
      91             : 
      92         570 :   log_debug ("register: interface %v queue-id %u thread %u", hi->name,
      93             :              queue_id, thread_index);
      94             : 
      95         570 :   return queue_index;
      96             : }
      97             : 
      98             : void
      99           0 : vnet_hw_if_unregister_rx_queue (vnet_main_t *vnm, u32 queue_index)
     100             : {
     101           0 :   vnet_interface_main_t *im = &vnm->interface_main;
     102             :   vnet_hw_if_rx_queue_t *rxq;
     103           0 :   rxq = vnet_hw_if_get_rx_queue (vnm, queue_index);
     104           0 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, rxq->hw_if_index);
     105             :   u64 key;
     106             : 
     107           0 :   key = rx_queue_key (rxq->hw_if_index, rxq->queue_id);
     108           0 :   hash_unset_mem_free (&im->rxq_index_by_hw_if_index_and_queue_id, &key);
     109             : 
     110           0 :   for (int i = 0; i < vec_len (hi->rx_queue_indices); i++)
     111           0 :     if (hi->rx_queue_indices[i] == queue_index)
     112             :       {
     113           0 :         vec_del1 (hi->rx_queue_indices, i);
     114           0 :         break;
     115             :       }
     116             : 
     117           0 :   log_debug ("unregister: interface %v queue-id %u", hi->name, rxq->queue_id);
     118           0 :   pool_put_index (im->hw_if_rx_queues, queue_index);
     119           0 : }
     120             : 
     121             : void
     122        4135 : vnet_hw_if_unregister_all_rx_queues (vnet_main_t *vnm, u32 hw_if_index)
     123             : {
     124        4135 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
     125        4135 :   vnet_interface_main_t *im = &vnm->interface_main;
     126             :   vnet_hw_if_rx_queue_t *rxq;
     127             :   vlib_main_t *vm;
     128             :   vnet_hw_if_rx_node_runtime_t *rt;
     129             :   u64 key;
     130             :   u32 queue_index;
     131             : 
     132        4135 :   log_debug ("unregister_all: interface %v", hi->name);
     133             : 
     134        4699 :   for (int i = 0; i < vec_len (hi->rx_queue_indices); i++)
     135             :     {
     136         564 :       rxq = vnet_hw_if_get_rx_queue (vnm, hi->rx_queue_indices[i]);
     137         564 :       key = rx_queue_key (rxq->hw_if_index, rxq->queue_id);
     138         564 :       if (PREDICT_FALSE (rxq->mode == VNET_HW_IF_RX_MODE_INTERRUPT ||
     139             :                          rxq->mode == VNET_HW_IF_RX_MODE_ADAPTIVE))
     140             :         {
     141         252 :           vm = vlib_get_main_by_index (rxq->thread_index);
     142         252 :           queue_index = vnet_hw_if_get_rx_queue_index_by_id (vnm, hw_if_index,
     143             :                                                              rxq->queue_id);
     144         252 :           rt = vlib_node_get_runtime_data (vm, hi->input_node_index);
     145         252 :           clib_interrupt_clear (rt->rxq_interrupts, queue_index);
     146             :         }
     147         564 :       hash_unset_mem_free (&im->rxq_index_by_hw_if_index_and_queue_id, &key);
     148             : 
     149         564 :       pool_put_index (im->hw_if_rx_queues, hi->rx_queue_indices[i]);
     150             :     }
     151             : 
     152        4135 :   vec_free (hi->rx_queue_indices);
     153        4135 : }
     154             : 
     155             : void
     156         566 : vnet_hw_if_set_rx_queue_file_index (vnet_main_t *vnm, u32 queue_index,
     157             :                                     u32 file_index)
     158             : {
     159         566 :   vnet_hw_if_rx_queue_t *rxq = vnet_hw_if_get_rx_queue (vnm, queue_index);
     160         566 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, rxq->hw_if_index);
     161             : 
     162         566 :   rxq->file_index = file_index;
     163         566 :   clib_file_set_polling_thread (&file_main, file_index, rxq->thread_index);
     164         566 :   log_debug ("set_file_index: interface %v queue-id %u file-index %u",
     165             :              hi->name, rxq->queue_id, file_index);
     166         566 : }
     167             : 
     168             : void
     169         578 : vnet_hw_if_set_input_node (vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
     170             : {
     171         578 :   vlib_main_t *vm = vlib_get_main ();
     172         578 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
     173         578 :   hi->input_node_index = node_index;
     174         578 :   log_debug ("set_input_node: node %U for interface %v", format_vlib_node_name,
     175             :              vm, node_index, hi->name);
     176         578 : }
     177             : 
     178             : int
     179         570 : vnet_hw_if_set_rx_queue_mode (vnet_main_t *vnm, u32 queue_index,
     180             :                               vnet_hw_if_rx_mode mode)
     181             : {
     182         570 :   vnet_hw_if_rx_queue_t *rxq = vnet_hw_if_get_rx_queue (vnm, queue_index);
     183         570 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, rxq->hw_if_index);
     184         570 :   vnet_device_class_t *dc = vnet_get_device_class (vnm, hi->dev_class_index);
     185             : 
     186         570 :   ASSERT (mode != VNET_HW_IF_RX_MODE_UNKNOWN);
     187             : 
     188         570 :   if (mode == VNET_HW_IF_RX_MODE_DEFAULT)
     189          14 :     mode = hi->default_rx_mode;
     190             : 
     191         570 :   if (rxq->mode == mode)
     192             :     {
     193         318 :       log_debug ("set_rx_queue_mode: interface %v queue-id %u mode "
     194             :                  "unchanged (%U)",
     195             :                  hi->name, rxq->queue_id, format_vnet_hw_if_rx_mode, mode);
     196         318 :       return 0;
     197             :     }
     198             : 
     199         252 :   if (dc->rx_mode_change_function)
     200             :     {
     201         252 :       clib_error_t *err = dc->rx_mode_change_function (vnm, rxq->hw_if_index,
     202             :                                                        rxq->queue_id, mode);
     203         252 :       if (err)
     204             :         {
     205           0 :           log_err ("setting rx mode on the interface %v queue-id %u failed.\n"
     206             :                    "   %U",
     207             :                    hi->name, rxq->queue_id, format_clib_error, err);
     208           0 :           clib_error_free (err);
     209           0 :           return VNET_API_ERROR_UNSUPPORTED;
     210             :         }
     211             :     }
     212             : 
     213         252 :   rxq->mode = mode;
     214         252 :   log_debug ("set_rx_queue_mode: interface %v queue-id %u mode set to %U",
     215             :              hi->name, rxq->queue_id, format_vnet_hw_if_rx_mode, mode);
     216         252 :   return 0;
     217             : }
     218             : 
     219             : vnet_hw_if_rx_mode
     220          14 : vnet_hw_if_get_rx_queue_mode (vnet_main_t *vnm, u32 queue_index)
     221             : {
     222          14 :   vnet_hw_if_rx_queue_t *rxq = vnet_hw_if_get_rx_queue (vnm, queue_index);
     223          14 :   return rxq->mode;
     224             : }
     225             : 
     226             : void
     227           0 : vnet_hw_if_set_rx_queue_thread_index (vnet_main_t *vnm, u32 queue_index,
     228             :                                       u32 thread_index)
     229             : {
     230           0 :   vnet_hw_if_rx_queue_t *rxq = vnet_hw_if_get_rx_queue (vnm, queue_index);
     231           0 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, rxq->hw_if_index);
     232             : 
     233           0 :   rxq->thread_index = thread_index;
     234             : 
     235           0 :   if (rxq->file_index != ~0)
     236           0 :     clib_file_set_polling_thread (&file_main, rxq->file_index, thread_index);
     237             : 
     238           0 :   log_debug ("set_rx_queue_thread_index: interface %v queue-id %u "
     239             :              "thread-index set to %u",
     240             :              hi->name, rxq->queue_id, thread_index);
     241           0 : }
     242             : 
     243             : vnet_hw_if_rxq_poll_vector_t *
     244      120328 : vnet_hw_if_generate_rxq_int_poll_vector (vlib_main_t *vm,
     245             :                                          vlib_node_runtime_t *node)
     246             : {
     247      120328 :   vnet_hw_if_rx_node_runtime_t *rt = (void *) node->runtime_data;
     248      120328 :   vnet_main_t *vnm = vnet_get_main ();
     249      120328 :   int int_num = -1;
     250             : 
     251      120328 :   ASSERT (node->state == VLIB_NODE_STATE_INTERRUPT);
     252             : 
     253      120328 :   vec_reset_length (rt->rxq_vector_int);
     254             : 
     255      307462 :   while ((int_num = clib_interrupt_get_next (rt->rxq_interrupts, int_num)) !=
     256             :          -1)
     257             :     {
     258      187134 :       vnet_hw_if_rx_queue_t *rxq = vnet_hw_if_get_rx_queue (vnm, int_num);
     259             :       vnet_hw_if_rxq_poll_vector_t *pv;
     260             : 
     261      187134 :       clib_interrupt_clear (rt->rxq_interrupts, int_num);
     262             : 
     263      187134 :       vec_add2 (rt->rxq_vector_int, pv, 1);
     264      187134 :       pv->dev_instance = rxq->dev_instance;
     265      187134 :       pv->queue_id = rxq->queue_id;
     266             :     }
     267      120328 :   return rt->rxq_vector_int;
     268             : }
     269             : 
     270             : /*
     271             :  * fd.io coding-style-patch-verification: ON
     272             :  *
     273             :  * Local Variables:
     274             :  * eval: (c-set-style "gnu")
     275             :  * End:
     276             :  */

Generated by: LCOV version 1.14