2 * vnet/pipeline.h: software pipeline
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * #define NSTAGES 3 or whatever
23 * If using an aux data vector - to hold bihash keys or some such:
25 * #define AUX_DATA_TYPE my_aux_data_t
27 * <Define pipeline stages>
29 * #include <vnet/pipeline.h>
31 * static uword my_node_fn (vlib_main_t * vm,
32 * vlib_node_runtime_t * node,
33 * vlib_frame_t * frame)
35 * return dispatch_pipeline (vm, node, frame);
41 #error files which #include <vnet/pipeline.h> must define NSTAGES
45 #define STAGE_INLINE inline
48 /* Unless the user wants the aux data scheme, don't configure it */
52 #define AUX_DATA_PTR(pi)
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)
60 * A prefetch stride of 2 is quasi-equivalent to doubling the number
61 * of stages with every other pipeline stage empty.
65 * This is a typical first pipeline stage, which prefetches
66 * buffer metadata and the first line of pkt data.
69 * #define stage0 generic_stage0
71 * This implementation won't use the aux data argument
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)
77 vlib_prefetch_buffer_header (b, STORE);
78 CLIB_PREFETCH (b->data, CLIB_CACHE_LINE_BYTES, STORE);
83 static STAGE_INLINE uword
84 dispatch_pipeline (vlib_main_t * vm,
85 vlib_node_runtime_t * node, vlib_frame_t * frame)
90 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
91 u16 nexts[VLIB_FRAME_SIZE];
94 n_left_from = frame->n_vectors;
95 from = vlib_frame_vector_args (frame);
96 vlib_get_buffers (vm, from, bufs, n_left_from);
98 for (pi = 0; pi < NSTAGES - 1; pi++)
100 if (pi == n_left_from)
102 stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
105 for (; pi < n_left_from; pi++)
107 stage0 (vm, node, bufs[pi]);
109 last_stage (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
112 for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
114 if (((pi - 1) >= 0) && ((pi - 1) < n_left_from))
116 last_stage (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
119 vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
120 return frame->n_vectors;
125 static STAGE_INLINE uword
126 dispatch_pipeline (vlib_main_t * vm,
127 vlib_node_runtime_t * node, vlib_frame_t * frame)
132 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
133 u16 nexts[VLIB_FRAME_SIZE];
136 n_left_from = frame->n_vectors;
137 from = vlib_frame_vector_args (frame);
138 vlib_get_buffers (vm, from, bufs, n_left_from);
140 for (pi = 0; pi < NSTAGES - 1; pi++)
142 if (pi == n_left_from)
144 stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
146 stage1 (vm, node, bufs[pi - 1]);
149 for (; pi < n_left_from; pi++)
151 stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
152 stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
154 last_stage (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
157 for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
159 if (((pi - 1) >= 0) && ((pi - 1) < n_left_from))
160 stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
161 if (((pi - 2) >= 0) && ((pi - 2) < n_left_from))
163 last_stage (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
166 vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
167 return frame->n_vectors;
172 static STAGE_INLINE uword
173 dispatch_pipeline (vlib_main_t * vm,
174 vlib_node_runtime_t * node, vlib_frame_t * frame)
179 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
180 u16 nexts[VLIB_FRAME_SIZE];
183 n_left_from = frame->n_vectors;
184 from = vlib_frame_vector_args (frame);
185 vlib_get_buffers (vm, from, bufs, n_left_from);
187 for (pi = 0; pi < NSTAGES - 1; pi++)
189 if (pi == n_left_from)
191 stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
193 stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
195 stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
198 for (; pi < n_left_from; pi++)
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));
204 last_stage (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
207 for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
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))
215 last_stage (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
218 vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
219 return frame->n_vectors;
224 static STAGE_INLINE uword
225 dispatch_pipeline (vlib_main_t * vm,
226 vlib_node_runtime_t * node, vlib_frame_t * frame)
231 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
232 u16 nexts[VLIB_FRAME_SIZE];
235 n_left_from = frame->n_vectors;
236 from = vlib_frame_vector_args (frame);
237 vlib_get_buffers (vm, from, bufs, n_left_from);
239 for (pi = 0; pi < NSTAGES - 1; pi++)
241 if (pi == n_left_from)
243 stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
245 stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
247 stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
249 stage3 (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
252 for (; pi < n_left_from; pi++)
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));
259 last_stage (vm, node, bufs[pi - 4] AUX_DATA_PTR (pi - 4));
262 for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
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))
272 last_stage (vm, node, bufs[pi - 4] AUX_DATA_PTR (pi - 4));
275 vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
276 return frame->n_vectors;
281 static STAGE_INLINE uword
282 dispatch_pipeline (vlib_main_t * vm,
283 vlib_node_runtime_t * node, vlib_frame_t * frame)
288 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
289 u16 nexts[VLIB_FRAME_SIZE];
292 n_left_from = frame->n_vectors;
293 from = vlib_frame_vector_args (frame);
294 vlib_get_buffers (vm, from, bufs, n_left_from);
296 for (pi = 0; pi < NSTAGES - 1; pi++)
298 if (pi == n_left_from)
300 stage0 (vm, node, bufs[pi] AUX_DATA_PTR (pi));
302 stage1 (vm, node, bufs[pi - 1] AUX_DATA_PTR (pi - 1));
304 stage2 (vm, node, bufs[pi - 2] AUX_DATA_PTR (pi - 2));
306 stage3 (vm, node, bufs[pi - 3] AUX_DATA_PTR (pi - 3));
308 stage4 (vm, node, bufs[pi - 4] AUX_DATA_PTR (pi - 4));
311 for (; pi < n_left_from; pi++)
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));
319 last_stage (vm, node, bufs[pi - 5] AUX_DATA_PTR (pi - 5));
322 for (; pi < (n_left_from + (NSTAGES - 1)); pi++)
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))
334 last_stage (vm, node, bufs[pi - 5] AUX_DATA_PTR (pi - 5));
337 vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
338 return frame->n_vectors;
343 * fd.io coding-style-patch-verification: ON
346 * eval: (c-set-style "gnu")