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 * <Define pipeline stages>
25 * #include <vnet/pipeline.h>
27 * static uword my_node_fn (vlib_main_t * vm,
28 * vlib_node_runtime_t * node,
29 * vlib_frame_t * frame)
31 * return dispatch_pipeline (vm, node, frame);
37 #error files which #include <vnet/pipeline.h> must define NSTAGES
41 #define STAGE_INLINE inline
45 * A prefetch stride of 2 is quasi-equivalent to doubling the number
46 * of stages with every other pipeline stage empty.
50 * This is a typical first pipeline stage, which prefetches
51 * buffer metadata and the first line of pkt data.
53 * #define stage0 generic_stage0
55 static STAGE_INLINE void
56 generic_stage0 (vlib_main_t * vm,
57 vlib_node_runtime_t * node, u32 buffer_index)
59 /* generic default stage 0 here */
60 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_index);
61 vlib_prefetch_buffer_header (b, STORE);
62 CLIB_PREFETCH (b->data, CLIB_CACHE_LINE_BYTES, STORE);
67 static STAGE_INLINE uword
68 dispatch_pipeline (vlib_main_t * vm,
69 vlib_node_runtime_t * node, vlib_frame_t * frame)
71 u32 *from = vlib_frame_vector_args (frame);
72 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
75 n_left_from = frame->n_vectors;
76 next_index = node->cached_next_index;
78 while (n_left_from > 0)
80 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
82 pi_limit = clib_min (n_left_from, n_left_to_next);
84 for (pi = 0; pi < NSTAGES - 1; pi++)
88 stage0 (vm, node, from[pi]);
91 for (; pi < pi_limit; pi++)
93 stage0 (vm, node, from[pi]);
94 to_next[0] = from[pi - 1];
97 next0 = last_stage (vm, node, from[pi - 1]);
98 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
99 to_next, n_left_to_next,
100 from[pi - 1], next0);
102 if ((int) n_left_to_next < 0 && n_left_from > 0)
103 vlib_get_next_frame (vm, node, next_index, to_next,
107 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
109 if (((pi - 1) >= 0) && ((pi - 1) < pi_limit))
111 to_next[0] = from[pi - 1];
114 next0 = last_stage (vm, node, from[pi - 1]);
115 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
116 to_next, n_left_to_next,
117 from[pi - 1], next0);
119 if ((int) n_left_to_next < 0 && n_left_from > 0)
120 vlib_get_next_frame (vm, node, next_index, to_next,
124 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
127 return frame->n_vectors;
132 static STAGE_INLINE uword
133 dispatch_pipeline (vlib_main_t * vm,
134 vlib_node_runtime_t * node, vlib_frame_t * frame)
136 u32 *from = vlib_frame_vector_args (frame);
137 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
140 n_left_from = frame->n_vectors;
141 next_index = node->cached_next_index;
143 while (n_left_from > 0)
145 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
147 pi_limit = clib_min (n_left_from, n_left_to_next);
149 for (pi = 0; pi < NSTAGES - 1; pi++)
153 stage0 (vm, node, from[pi]);
155 stage1 (vm, node, from[pi - 1]);
158 for (; pi < pi_limit; pi++)
160 stage0 (vm, node, from[pi]);
161 stage1 (vm, node, from[pi - 1]);
162 to_next[0] = from[pi - 2];
165 next0 = last_stage (vm, node, from[pi - 2]);
166 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
167 to_next, n_left_to_next,
168 from[pi - 2], next0);
170 if ((int) n_left_to_next < 0 && n_left_from > 0)
171 vlib_get_next_frame (vm, node, next_index, to_next,
176 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
178 if (((pi - 1) >= 0) && ((pi - 1) < pi_limit))
179 stage1 (vm, node, from[pi - 1]);
180 if (((pi - 2) >= 0) && ((pi - 2) < pi_limit))
182 to_next[0] = from[pi - 2];
185 next0 = last_stage (vm, node, from[pi - 2]);
186 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
187 to_next, n_left_to_next,
188 from[pi - 2], next0);
190 if ((int) n_left_to_next < 0 && n_left_from > 0)
191 vlib_get_next_frame (vm, node, next_index, to_next,
196 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
199 return frame->n_vectors;
204 static STAGE_INLINE uword
205 dispatch_pipeline (vlib_main_t * vm,
206 vlib_node_runtime_t * node, vlib_frame_t * frame)
208 u32 *from = vlib_frame_vector_args (frame);
209 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
212 n_left_from = frame->n_vectors;
213 next_index = node->cached_next_index;
215 while (n_left_from > 0)
217 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
219 pi_limit = clib_min (n_left_from, n_left_to_next);
221 for (pi = 0; pi < NSTAGES - 1; pi++)
225 stage0 (vm, node, from[pi]);
227 stage1 (vm, node, from[pi - 1]);
229 stage2 (vm, node, from[pi - 2]);
232 for (; pi < pi_limit; pi++)
234 stage0 (vm, node, from[pi]);
235 stage1 (vm, node, from[pi - 1]);
236 stage2 (vm, node, from[pi - 2]);
237 to_next[0] = from[pi - 3];
240 next0 = last_stage (vm, node, from[pi - 3]);
241 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
242 to_next, n_left_to_next,
243 from[pi - 3], next0);
245 if ((int) n_left_to_next < 0 && n_left_from > 0)
246 vlib_get_next_frame (vm, node, next_index, to_next,
251 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
253 if (((pi - 1) >= 0) && ((pi - 1) < pi_limit))
254 stage1 (vm, node, from[pi - 1]);
255 if (((pi - 2) >= 0) && ((pi - 2) < pi_limit))
256 stage2 (vm, node, from[pi - 2]);
257 if (((pi - 3) >= 0) && ((pi - 3) < pi_limit))
259 to_next[0] = from[pi - 3];
262 next0 = last_stage (vm, node, from[pi - 3]);
263 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
264 to_next, n_left_to_next,
265 from[pi - 3], next0);
267 if ((int) n_left_to_next < 0 && n_left_from > 0)
268 vlib_get_next_frame (vm, node, next_index, to_next,
273 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
276 return frame->n_vectors;
282 static STAGE_INLINE uword
283 dispatch_pipeline (vlib_main_t * vm,
284 vlib_node_runtime_t * node, vlib_frame_t * frame)
286 u32 *from = vlib_frame_vector_args (frame);
287 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
290 n_left_from = frame->n_vectors;
291 next_index = node->cached_next_index;
293 while (n_left_from > 0)
295 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
297 pi_limit = clib_min (n_left_from, n_left_to_next);
299 for (pi = 0; pi < NSTAGES - 1; pi++)
303 stage0 (vm, node, from[pi]);
305 stage1 (vm, node, from[pi - 1]);
307 stage2 (vm, node, from[pi - 2]);
309 stage3 (vm, node, from[pi - 3]);
312 for (; pi < pi_limit; pi++)
314 stage0 (vm, node, from[pi]);
315 stage1 (vm, node, from[pi - 1]);
316 stage2 (vm, node, from[pi - 2]);
317 stage3 (vm, node, from[pi - 3]);
318 to_next[0] = from[pi - 4];
321 next0 = last_stage (vm, node, from[pi - 4]);
322 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
323 to_next, n_left_to_next,
324 from[pi - 4], next0);
326 if ((int) n_left_to_next < 0 && n_left_from > 0)
327 vlib_get_next_frame (vm, node, next_index, to_next,
332 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
334 if (((pi - 1) >= 0) && ((pi - 1) < pi_limit))
335 stage1 (vm, node, from[pi - 1]);
336 if (((pi - 2) >= 0) && ((pi - 2) < pi_limit))
337 stage2 (vm, node, from[pi - 2]);
338 if (((pi - 3) >= 0) && ((pi - 3) < pi_limit))
339 stage3 (vm, node, from[pi - 3]);
340 if (((pi - 4) >= 0) && ((pi - 4) < pi_limit))
342 to_next[0] = from[pi - 4];
345 next0 = last_stage (vm, node, from[pi - 4]);
346 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
347 to_next, n_left_to_next,
348 from[pi - 4], next0);
350 if ((int) n_left_to_next < 0 && n_left_from > 0)
351 vlib_get_next_frame (vm, node, next_index, to_next,
356 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
359 return frame->n_vectors;
364 static STAGE_INLINE uword
365 dispatch_pipeline (vlib_main_t * vm,
366 vlib_node_runtime_t * node, vlib_frame_t * frame)
368 u32 *from = vlib_frame_vector_args (frame);
369 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
372 n_left_from = frame->n_vectors;
373 next_index = node->cached_next_index;
375 while (n_left_from > 0)
377 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
379 pi_limit = clib_min (n_left_from, n_left_to_next);
381 for (pi = 0; pi < NSTAGES - 1; pi++)
385 stage0 (vm, node, from[pi]);
387 stage1 (vm, node, from[pi - 1]);
389 stage2 (vm, node, from[pi - 2]);
391 stage3 (vm, node, from[pi - 3]);
393 stage4 (vm, node, from[pi - 4]);
396 for (; pi < pi_limit; pi++)
398 stage0 (vm, node, from[pi]);
399 stage1 (vm, node, from[pi - 1]);
400 stage2 (vm, node, from[pi - 2]);
401 stage3 (vm, node, from[pi - 3]);
402 stage4 (vm, node, from[pi - 4]);
403 to_next[0] = from[pi - 5];
406 next0 = last_stage (vm, node, from[pi - 5]);
407 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
408 to_next, n_left_to_next,
409 from[pi - 5], next0);
411 if ((int) n_left_to_next < 0 && n_left_from > 0)
412 vlib_get_next_frame (vm, node, next_index, to_next,
417 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
419 if (((pi - 1) >= 0) && ((pi - 1) < pi_limit))
420 stage1 (vm, node, from[pi - 1]);
421 if (((pi - 2) >= 0) && ((pi - 2) < pi_limit))
422 stage2 (vm, node, from[pi - 2]);
423 if (((pi - 3) >= 0) && ((pi - 3) < pi_limit))
424 stage3 (vm, node, from[pi - 3]);
425 if (((pi - 4) >= 0) && ((pi - 4) < pi_limit))
426 stage4 (vm, node, from[pi - 4]);
427 if (((pi - 5) >= 0) && ((pi - 5) < pi_limit))
429 to_next[0] = from[pi - 5];
432 next0 = last_stage (vm, node, from[pi - 5]);
433 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
434 to_next, n_left_to_next,
435 from[pi - 5], next0);
437 if ((int) n_left_to_next < 0 && n_left_from > 0)
438 vlib_get_next_frame (vm, node, next_index, to_next,
443 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
446 return frame->n_vectors;
451 * fd.io coding-style-patch-verification: ON
454 * eval: (c-set-style "gnu")