blob: a4aa5cf5277df684e26bca7d6da6f5011a22bb49 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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 * <Define pipeline stages>
24 *
25 * #include <vnet/pipeline.h>
Dave Barachba868bb2016-08-08 09:51:21 -040026 *
Ed Warnickecb9cada2015-12-08 15:45:58 -070027 * static uword my_node_fn (vlib_main_t * vm,
28 * vlib_node_runtime_t * node,
29 * vlib_frame_t * frame)
30 * {
31 * return dispatch_pipeline (vm, node, frame);
32 * }
Dave Barachba868bb2016-08-08 09:51:21 -040033 *
Ed Warnickecb9cada2015-12-08 15:45:58 -070034 */
35
36#ifndef NSTAGES
37#error files which #include <vnet/pipeline.h> must define NSTAGES
38#endif
39
40#ifndef STAGE_INLINE
41#define STAGE_INLINE inline
42#endif
43
Dave Barachba868bb2016-08-08 09:51:21 -040044/*
Ed Warnickecb9cada2015-12-08 15:45:58 -070045 * A prefetch stride of 2 is quasi-equivalent to doubling the number
46 * of stages with every other pipeline stage empty.
47 */
48
Dave Barachba868bb2016-08-08 09:51:21 -040049/*
50 * This is a typical first pipeline stage, which prefetches
51 * buffer metadata and the first line of pkt data.
Ed Warnickecb9cada2015-12-08 15:45:58 -070052 * To use it:
53 * #define stage0 generic_stage0
54 */
Dave Barachba868bb2016-08-08 09:51:21 -040055static STAGE_INLINE void
56generic_stage0 (vlib_main_t * vm,
57 vlib_node_runtime_t * node, u32 buffer_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -070058{
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);
63}
64
65#if NSTAGES == 2
66
67static STAGE_INLINE uword
68dispatch_pipeline (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -040069 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -070070{
Dave Barachba868bb2016-08-08 09:51:21 -040071 u32 *from = vlib_frame_vector_args (frame);
72 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070073 int pi, pi_limit;
Dave Barachba868bb2016-08-08 09:51:21 -040074
Ed Warnickecb9cada2015-12-08 15:45:58 -070075 n_left_from = frame->n_vectors;
76 next_index = node->cached_next_index;
Dave Barachba868bb2016-08-08 09:51:21 -040077
78 while (n_left_from > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -070079 {
80 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Ed Warnickecb9cada2015-12-08 15:45:58 -070081
Dave Barachba868bb2016-08-08 09:51:21 -040082 pi_limit = clib_min (n_left_from, n_left_to_next);
83
84 for (pi = 0; pi < NSTAGES - 1; pi++)
85 {
86 if (pi == pi_limit)
87 break;
88 stage0 (vm, node, from[pi]);
89 }
90
91 for (; pi < pi_limit; pi++)
92 {
93 stage0 (vm, node, from[pi]);
94 to_next[0] = from[pi - 1];
95 to_next++;
96 n_left_to_next--;
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);
101 n_left_from--;
102 if ((int) n_left_to_next < 0 && n_left_from > 0)
103 vlib_get_next_frame (vm, node, next_index, to_next,
104 n_left_to_next);
105 }
106
107 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
108 {
109 if (((pi - 1) >= 0) && ((pi - 1) < pi_limit))
110 {
111 to_next[0] = from[pi - 1];
112 to_next++;
113 n_left_to_next--;
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);
118 n_left_from--;
119 if ((int) n_left_to_next < 0 && n_left_from > 0)
120 vlib_get_next_frame (vm, node, next_index, to_next,
121 n_left_to_next);
122 }
123 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
125 from += pi_limit;
126 }
127 return frame->n_vectors;
128}
129#endif
130
131#if NSTAGES == 3
132static STAGE_INLINE uword
133dispatch_pipeline (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400134 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700135{
Dave Barachba868bb2016-08-08 09:51:21 -0400136 u32 *from = vlib_frame_vector_args (frame);
137 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700138 int pi, pi_limit;
Dave Barachba868bb2016-08-08 09:51:21 -0400139
Ed Warnickecb9cada2015-12-08 15:45:58 -0700140 n_left_from = frame->n_vectors;
141 next_index = node->cached_next_index;
Dave Barachba868bb2016-08-08 09:51:21 -0400142
143 while (n_left_from > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700144 {
145 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Dave Barachba868bb2016-08-08 09:51:21 -0400146
Ed Warnickecb9cada2015-12-08 15:45:58 -0700147 pi_limit = clib_min (n_left_from, n_left_to_next);
Dave Barachba868bb2016-08-08 09:51:21 -0400148
149 for (pi = 0; pi < NSTAGES - 1; pi++)
150 {
151 if (pi == pi_limit)
152 break;
153 stage0 (vm, node, from[pi]);
154 if (pi - 1 >= 0)
155 stage1 (vm, node, from[pi - 1]);
156 }
157
158 for (; pi < pi_limit; pi++)
159 {
160 stage0 (vm, node, from[pi]);
161 stage1 (vm, node, from[pi - 1]);
162 to_next[0] = from[pi - 2];
163 to_next++;
164 n_left_to_next--;
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);
169 n_left_from--;
170 if ((int) n_left_to_next < 0 && n_left_from > 0)
171 vlib_get_next_frame (vm, node, next_index, to_next,
172 n_left_to_next);
173 }
174
175
176 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
177 {
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))
181 {
182 to_next[0] = from[pi - 2];
183 to_next++;
184 n_left_to_next--;
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);
189 n_left_from--;
190 if ((int) n_left_to_next < 0 && n_left_from > 0)
191 vlib_get_next_frame (vm, node, next_index, to_next,
192 n_left_to_next);
193 }
194 }
195
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
197 from += pi_limit;
198 }
199 return frame->n_vectors;
200}
201#endif
202
203#if NSTAGES == 4
204static STAGE_INLINE uword
205dispatch_pipeline (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400206 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700207{
Dave Barachba868bb2016-08-08 09:51:21 -0400208 u32 *from = vlib_frame_vector_args (frame);
209 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210 int pi, pi_limit;
Dave Barachba868bb2016-08-08 09:51:21 -0400211
Ed Warnickecb9cada2015-12-08 15:45:58 -0700212 n_left_from = frame->n_vectors;
213 next_index = node->cached_next_index;
Dave Barachba868bb2016-08-08 09:51:21 -0400214
215 while (n_left_from > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216 {
217 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Dave Barachba868bb2016-08-08 09:51:21 -0400218
Ed Warnickecb9cada2015-12-08 15:45:58 -0700219 pi_limit = clib_min (n_left_from, n_left_to_next);
Dave Barachba868bb2016-08-08 09:51:21 -0400220
221 for (pi = 0; pi < NSTAGES - 1; pi++)
222 {
223 if (pi == pi_limit)
224 break;
225 stage0 (vm, node, from[pi]);
226 if (pi - 1 >= 0)
227 stage1 (vm, node, from[pi - 1]);
228 if (pi - 2 >= 0)
229 stage2 (vm, node, from[pi - 2]);
230 }
231
232 for (; pi < pi_limit; pi++)
233 {
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];
238 to_next++;
239 n_left_to_next--;
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);
244 n_left_from--;
245 if ((int) n_left_to_next < 0 && n_left_from > 0)
246 vlib_get_next_frame (vm, node, next_index, to_next,
247 n_left_to_next);
248 }
249
250
251 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
252 {
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))
258 {
259 to_next[0] = from[pi - 3];
260 to_next++;
261 n_left_to_next--;
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);
266 n_left_from--;
267 if ((int) n_left_to_next < 0 && n_left_from > 0)
268 vlib_get_next_frame (vm, node, next_index, to_next,
269 n_left_to_next);
270 }
271 }
272
273 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
274 from += pi_limit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700275 }
276 return frame->n_vectors;
277}
278#endif
279
280
281#if NSTAGES == 5
282static STAGE_INLINE uword
283dispatch_pipeline (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400284 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285{
Dave Barachba868bb2016-08-08 09:51:21 -0400286 u32 *from = vlib_frame_vector_args (frame);
287 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700288 int pi, pi_limit;
Dave Barachba868bb2016-08-08 09:51:21 -0400289
Ed Warnickecb9cada2015-12-08 15:45:58 -0700290 n_left_from = frame->n_vectors;
291 next_index = node->cached_next_index;
Dave Barachba868bb2016-08-08 09:51:21 -0400292
293 while (n_left_from > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700294 {
295 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Dave Barachba868bb2016-08-08 09:51:21 -0400296
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297 pi_limit = clib_min (n_left_from, n_left_to_next);
Dave Barachba868bb2016-08-08 09:51:21 -0400298
299 for (pi = 0; pi < NSTAGES - 1; pi++)
300 {
301 if (pi == pi_limit)
302 break;
303 stage0 (vm, node, from[pi]);
304 if (pi - 1 >= 0)
305 stage1 (vm, node, from[pi - 1]);
306 if (pi - 2 >= 0)
307 stage2 (vm, node, from[pi - 2]);
308 if (pi - 3 >= 0)
309 stage3 (vm, node, from[pi - 3]);
310 }
311
312 for (; pi < pi_limit; pi++)
313 {
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];
319 to_next++;
320 n_left_to_next--;
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);
325 n_left_from--;
326 if ((int) n_left_to_next < 0 && n_left_from > 0)
327 vlib_get_next_frame (vm, node, next_index, to_next,
328 n_left_to_next);
329 }
330
331
332 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
333 {
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))
341 {
342 to_next[0] = from[pi - 4];
343 to_next++;
344 n_left_to_next--;
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);
349 n_left_from--;
350 if ((int) n_left_to_next < 0 && n_left_from > 0)
351 vlib_get_next_frame (vm, node, next_index, to_next,
352 n_left_to_next);
353 }
354 }
355
356 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
357 from += pi_limit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358 }
359 return frame->n_vectors;
360}
361#endif
362
363#if NSTAGES == 6
364static STAGE_INLINE uword
365dispatch_pipeline (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400366 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700367{
Dave Barachba868bb2016-08-08 09:51:21 -0400368 u32 *from = vlib_frame_vector_args (frame);
369 u32 n_left_from, n_left_to_next, *to_next, next_index, next0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700370 int pi, pi_limit;
Dave Barachba868bb2016-08-08 09:51:21 -0400371
Ed Warnickecb9cada2015-12-08 15:45:58 -0700372 n_left_from = frame->n_vectors;
373 next_index = node->cached_next_index;
Dave Barachba868bb2016-08-08 09:51:21 -0400374
375 while (n_left_from > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700376 {
377 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Dave Barachba868bb2016-08-08 09:51:21 -0400378
Ed Warnickecb9cada2015-12-08 15:45:58 -0700379 pi_limit = clib_min (n_left_from, n_left_to_next);
Dave Barachba868bb2016-08-08 09:51:21 -0400380
381 for (pi = 0; pi < NSTAGES - 1; pi++)
382 {
383 if (pi == pi_limit)
384 break;
385 stage0 (vm, node, from[pi]);
386 if (pi - 1 >= 0)
387 stage1 (vm, node, from[pi - 1]);
388 if (pi - 2 >= 0)
389 stage2 (vm, node, from[pi - 2]);
390 if (pi - 3 >= 0)
391 stage3 (vm, node, from[pi - 3]);
392 if (pi - 4 >= 0)
393 stage4 (vm, node, from[pi - 4]);
394 }
395
396 for (; pi < pi_limit; pi++)
397 {
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];
404 to_next++;
405 n_left_to_next--;
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);
410 n_left_from--;
411 if ((int) n_left_to_next < 0 && n_left_from > 0)
412 vlib_get_next_frame (vm, node, next_index, to_next,
413 n_left_to_next);
414 }
415
416
417 for (; pi < (pi_limit + (NSTAGES - 1)); pi++)
418 {
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))
428 {
429 to_next[0] = from[pi - 5];
430 to_next++;
431 n_left_to_next--;
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);
436 n_left_from--;
437 if ((int) n_left_to_next < 0 && n_left_from > 0)
438 vlib_get_next_frame (vm, node, next_index, to_next,
439 n_left_to_next);
440 }
441 }
442
443 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
444 from += pi_limit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700445 }
446 return frame->n_vectors;
447}
448#endif
Dave Barachba868bb2016-08-08 09:51:21 -0400449
450/*
451 * fd.io coding-style-patch-verification: ON
452 *
453 * Local Variables:
454 * eval: (c-set-style "gnu")
455 * End:
456 */