LCOV - code coverage report
Current view: top level - vnet - pipeline.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 18 23 78.3 %
Date: 2023-10-26 01:39:38 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * vnet/pipeline.h: software pipeline
       3             :  *
       4             :  * Copyright (c) 2012 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : /*
      19             :  * Usage example.
      20             :  *
      21             :  * #define NSTAGES 3 or whatever
      22             :  *
      23             :  * If using an aux data vector - to hold bihash keys or some such:
      24             :  *
      25             :  * #define AUX_DATA_TYPE my_aux_data_t
      26             :  *
      27             :  * <Define pipeline stages>
      28             :  *
      29             :  * #include <vnet/pipeline.h>
      30             :  *
      31             :  * static uword my_node_fn (vlib_main_t * vm,
      32             :  *                               vlib_node_runtime_t * node,
      33             :  *                               vlib_frame_t * frame)
      34             :  * {
      35             :  *     return dispatch_pipeline (vm, node, frame);
      36             :  * }
      37             :  *
      38             :  */
      39             : 
      40             : #ifndef NSTAGES
      41             : #error files which #include <vnet/pipeline.h> must define NSTAGES
      42             : #endif
      43             : 
      44             : #ifndef STAGE_INLINE
      45             : #define STAGE_INLINE inline
      46             : #endif
      47             : 
      48             : /* Unless the user wants the aux data scheme, don't configure it */
      49             : #ifndef AUX_DATA_TYPE
      50             : #define AUX_DATA_ARG
      51             : #define AUX_DATA_DECL
      52             : #define AUX_DATA_PTR(pi)
      53             : #else
      54             : #define AUX_DATA_ARG ,##AUX_DATA_TYPE *ap
      55             : #define AUX_DATA_DECL AUX_DATA_TYPE aux_data[VLIB_FRAME_SIZE]
      56             : #define AUX_DATA_PTR(pi) ,aux_data +(pi)
      57             : #endif
      58             : 
      59             : /*
      60             :  * A prefetch stride of 2 is quasi-equivalent to doubling the number
      61             :  * of stages with every other pipeline stage empty.
      62             :  */
      63             : 
      64             : /*
      65             :  * This is a typical first pipeline stage, which prefetches
      66             :  * buffer metadata and the first line of pkt data.
      67             :  *
      68             :  * To use it:
      69             :  *  #define stage0 generic_stage0
      70             :  *
      71             :  * This implementation won't use the aux data argument
      72             :  */
      73             : static STAGE_INLINE void
      74             : generic_stage0 (vlib_main_t * vm,
      75             :                 vlib_node_runtime_t * node, vlib_buffer_t * b AUX_DATA_ARG)
      76             : {
      77             :   vlib_prefetch_buffer_header (b, STORE);
      78             :   clib_prefetch_store (b->data);
      79             : }
      80             : 
      81             : #if NSTAGES == 2
      82             : 
      83             : static STAGE_INLINE uword
      84             : dispatch_pipeline (vlib_main_t * vm,
      85             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
      86             : {
      87             :   u32 *from;
      88             :   u32 n_left_from;
      89             :   int pi;
      90             :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
      91             :   u16 nexts[VLIB_FRAME_SIZE];
      92             :   AUX_DATA_DECL;
      93             : 
      94             :   n_left_from = frame->n_vectors;
      95             :   from = vlib_frame_vector_args (frame);
      96             :   vlib_get_buffers (vm, from, bufs, n_left_from);
      97             : 
      98             :   for (pi = 0; pi < NSTAGES - 1; pi++)
      99             :     {
     100             :       if (pi == n_left_from)
     101             :         break;
     102             :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     103             :     }
     104             : 
     105             :   for (; pi < n_left_from; pi++)
     106             :     {
     107             :       stage0 (vm, node, bufs[pi]);
     108             :       nexts[pi - 1] =
     109             :         last_stage (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     110             :     }
     111             : 
     112             :   for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
     113             :     {
     114             :       if (((pi - 1) >= 0) && ((pi - 1) < n_left_from))
     115             :         nexts[pi - 1] =
     116             :           last_stage (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     117             :     }
     118             : 
     119             :   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
     120             :   return frame->n_vectors;
     121             : }
     122             : #endif
     123             : 
     124             : #if NSTAGES == 3
     125             : static STAGE_INLINE uword
     126           1 : dispatch_pipeline (vlib_main_t * vm,
     127             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
     128             : {
     129             :   u32 *from;
     130             :   u32 n_left_from;
     131             :   int pi;
     132             :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
     133             :   u16 nexts[VLIB_FRAME_SIZE];
     134             :   AUX_DATA_DECL;
     135             : 
     136           1 :   n_left_from = frame->n_vectors;
     137           1 :   from = vlib_frame_vector_args (frame);
     138           1 :   vlib_get_buffers (vm, from, bufs, n_left_from);
     139             : 
     140           2 :   for (pi = 0; pi < NSTAGES - 1; pi++)
     141             :     {
     142           2 :       if (pi == n_left_from)
     143           1 :         break;
     144           1 :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     145           1 :       if (pi - 1 >= 0)
     146           0 :         stage1 (vm, node, bufs[pi - 1]);
     147             :     }
     148             : 
     149           1 :   for (; pi < n_left_from; pi++)
     150             :     {
     151           0 :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     152           0 :       stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     153           0 :       nexts[pi - 2] =
     154           0 :         last_stage (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     155             :     }
     156             : 
     157           3 :   for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
     158             :     {
     159           2 :       if (((pi - 1) >= 0) && ((pi - 1) < n_left_from))
     160           1 :         stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     161           2 :       if (((pi - 2) >= 0) && ((pi - 2) < n_left_from))
     162           1 :         nexts[pi - 2] =
     163           1 :           last_stage (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     164             :     }
     165             : 
     166           1 :   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
     167           1 :   return frame->n_vectors;
     168             : }
     169             : #endif
     170             : 
     171             : #if NSTAGES == 4
     172             : static STAGE_INLINE uword
     173             : dispatch_pipeline (vlib_main_t * vm,
     174             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
     175             : {
     176             :   u32 *from;
     177             :   u32 n_left_from;
     178             :   int pi;
     179             :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
     180             :   u16 nexts[VLIB_FRAME_SIZE];
     181             :   AUX_DATA_DECL;
     182             : 
     183             :   n_left_from = frame->n_vectors;
     184             :   from = vlib_frame_vector_args (frame);
     185             :   vlib_get_buffers (vm, from, bufs, n_left_from);
     186             : 
     187             :   for (pi = 0; pi < NSTAGES - 1; pi++)
     188             :     {
     189             :       if (pi == n_left_from)
     190             :         break;
     191             :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     192             :       if (pi - 1 >= 0)
     193             :         stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     194             :       if (pi - 2 >= 0)
     195             :         stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     196             :     }
     197             : 
     198             :   for (; pi < n_left_from; pi++)
     199             :     {
     200             :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     201             :       stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     202             :       stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     203             :       nexts[pi - 3] =
     204             :         last_stage (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
     205             :     }
     206             : 
     207             :   for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
     208             :     {
     209             :       if (((pi - 1) >= 0) && ((pi - 1) < n_left_from))
     210             :         stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     211             :       if (((pi - 2) >= 0) && ((pi - 2) < n_left_from))
     212             :         stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     213             :       if (((pi - 3) >= 0) && ((pi - 3) < n_left_from))
     214             :         nexts[pi - 3] =
     215             :           last_stage (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
     216             :     }
     217             : 
     218             :   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
     219             :   return frame->n_vectors;
     220             : }
     221             : #endif
     222             : 
     223             : #if NSTAGES == 5
     224             : static STAGE_INLINE uword
     225             : dispatch_pipeline (vlib_main_t * vm,
     226             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
     227             : {
     228             :   u32 *from;
     229             :   u32 n_left_from;
     230             :   int pi;
     231             :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
     232             :   u16 nexts[VLIB_FRAME_SIZE];
     233             :   AUX_DATA_DECL;
     234             : 
     235             :   n_left_from = frame->n_vectors;
     236             :   from = vlib_frame_vector_args (frame);
     237             :   vlib_get_buffers (vm, from, bufs, n_left_from);
     238             : 
     239             :   for (pi = 0; pi < NSTAGES - 1; pi++)
     240             :     {
     241             :       if (pi == n_left_from)
     242             :         break;
     243             :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     244             :       if (pi - 1 >= 0)
     245             :         stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     246             :       if (pi - 2 >= 0)
     247             :         stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     248             :       if (pi - 3 >= 0)
     249             :         stage3 (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
     250             :     }
     251             : 
     252             :   for (; pi < n_left_from; pi++)
     253             :     {
     254             :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     255             :       stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     256             :       stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     257             :       stage3 (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
     258             :       nexts[pi - 4] =
     259             :         last_stage (vm, node, bufs[pi - 4] AUX_DATA_PTR (pi - 4));
     260             :     }
     261             : 
     262             :   for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
     263             :     {
     264             :       if (((pi - 1) >= 0) && ((pi - 1) < n_left_from))
     265             :         stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     266             :       if (((pi - 2) >= 0) && ((pi - 2) < n_left_from))
     267             :         stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     268             :       if (((pi - 3) >= 0) && ((pi - 3) < n_left_from))
     269             :         stage3 (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
     270             :       if (((pi - 4) >= 0) && ((pi - 4) < n_left_from))
     271             :         nexts[pi - 4] =
     272             :           last_stage (vm, node, bufs[pi - 4] AUX_DATA_PTR (pi - 4));
     273             :     }
     274             : 
     275             :   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
     276             :   return frame->n_vectors;
     277             : }
     278             : #endif
     279             : 
     280             : #if NSTAGES == 6
     281             : static STAGE_INLINE uword
     282             : dispatch_pipeline (vlib_main_t * vm,
     283             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
     284             : {
     285             :   u32 *from;
     286             :   u32 n_left_from;
     287             :   int pi;
     288             :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
     289             :   u16 nexts[VLIB_FRAME_SIZE];
     290             :   AUX_DATA_DECL;
     291             : 
     292             :   n_left_from = frame->n_vectors;
     293             :   from = vlib_frame_vector_args (frame);
     294             :   vlib_get_buffers (vm, from, bufs, n_left_from);
     295             : 
     296             :   for (pi = 0; pi < NSTAGES - 1; pi++)
     297             :     {
     298             :       if (pi == n_left_from)
     299             :         break;
     300             :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     301             :       if (pi - 1 >= 0)
     302             :         stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     303             :       if (pi - 2 >= 0)
     304             :         stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     305             :       if (pi - 3 >= 0)
     306             :         stage3 (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
     307             :       if (pi - 4 >= 0)
     308             :         stage4 (vm, node, bufs[pi - 4] AUX_DATA_PTR (pi - 4));
     309             :     }
     310             : 
     311             :   for (; pi < n_left_from; pi++)
     312             :     {
     313             :       stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
     314             :       stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     315             :       stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     316             :       stage3 (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
     317             :       stage4 (vm, node, bufs[pi - 4] AUX_DATA_PTR (pi - 4));
     318             :       nexts[pi - 5] =
     319             :         last_stage (vm, node, bufs[pi - 5] AUX_DATA_PTR (pi - 5));
     320             :     }
     321             : 
     322             :   for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
     323             :     {
     324             :       if (((pi - 1) >= 0) && ((pi - 1) < n_left_from))
     325             :         stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
     326             :       if (((pi - 2) >= 0) && ((pi - 2) < n_left_from))
     327             :         stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
     328             :       if (((pi - 3) >= 0) && ((pi - 3) < n_left_from))
     329             :         stage3 (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
     330             :       if (((pi - 4) >= 0) && ((pi - 4) < n_left_from))
     331             :         stage4 (vm, node, bufs[pi - 4] AUX_DATA_PTR (pi - 4));
     332             :       if (((pi - 5) >= 0) && ((pi - 5) < n_left_from))
     333             :         nexts[pi - 5] =
     334             :           last_stage (vm, node, bufs[pi - 5] AUX_DATA_PTR (pi - 5));
     335             :     }
     336             : 
     337             :   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
     338             :   return frame->n_vectors;
     339             : }
     340             : #endif
     341             : 
     342             : /*
     343             :  * fd.io coding-style-patch-verification: ON
     344             :  *
     345             :  * Local Variables:
     346             :  * eval: (c-set-style "gnu")
     347             :  * End:
     348             :  */

Generated by: LCOV version 1.14