pktgen: support mixed multi/single chunk pcap replay
[vpp.git] / src / vnet / pg / input.c
1 /*
2  * Copyright (c) 2015 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  * pg_input.c: buffer generator input
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39
40   /*
41    * To be honest, the packet generator needs an extreme
42    * makeover. Two key assumptions which drove the current implementation
43    * are no longer true. First, buffer managers implement a
44    * post-TX recycle list. Second, that packet generator performance
45    * is first-order important.
46    */
47
48 #include <vlib/vlib.h>
49 #include <vnet/pg/pg.h>
50 #include <vnet/vnet.h>
51 #include <vnet/ethernet/ethernet.h>
52 #include <vnet/feature/feature.h>
53 #include <vnet/devices/devices.h>
54
55 static int
56 validate_buffer_data2 (vlib_buffer_t * b, pg_stream_t * s,
57                        u32 data_offset, u32 n_bytes)
58 {
59   u8 *bd, *pd, *pm;
60   u32 i;
61
62   bd = b->data;
63   pd = s->fixed_packet_data + data_offset;
64   pm = s->fixed_packet_data_mask + data_offset;
65
66   if (pd + n_bytes >= vec_end (s->fixed_packet_data))
67     n_bytes = (pd < vec_end (s->fixed_packet_data)
68                ? vec_end (s->fixed_packet_data) - pd : 0);
69
70   for (i = 0; i < n_bytes; i++)
71     if ((bd[i] & pm[i]) != pd[i])
72       break;
73
74   if (i >= n_bytes)
75     return 1;
76
77   clib_warning ("buffer %U", format_vnet_buffer, b);
78   clib_warning ("differ at index %d", i);
79   clib_warning ("is     %U", format_hex_bytes, bd, n_bytes);
80   clib_warning ("mask   %U", format_hex_bytes, pm, n_bytes);
81   clib_warning ("expect %U", format_hex_bytes, pd, n_bytes);
82   return 0;
83 }
84
85 static int
86 validate_buffer_data (vlib_buffer_t * b, pg_stream_t * s)
87 {
88   return validate_buffer_data2 (b, s, 0, s->buffer_bytes);
89 }
90
91 always_inline void
92 set_1 (void *a0,
93        u64 v0, u64 v_min, u64 v_max, u32 n_bits, u32 is_net_byte_order)
94 {
95   ASSERT (v0 >= v_min && v0 <= v_max);
96   if (n_bits == BITS (u8))
97     {
98       ((u8 *) a0)[0] = v0;
99     }
100   else if (n_bits == BITS (u16))
101     {
102       if (is_net_byte_order)
103         v0 = clib_host_to_net_u16 (v0);
104       clib_mem_unaligned (a0, u16) = v0;
105     }
106   else if (n_bits == BITS (u32))
107     {
108       if (is_net_byte_order)
109         v0 = clib_host_to_net_u32 (v0);
110       clib_mem_unaligned (a0, u32) = v0;
111     }
112   else if (n_bits == BITS (u64))
113     {
114       if (is_net_byte_order)
115         v0 = clib_host_to_net_u64 (v0);
116       clib_mem_unaligned (a0, u64) = v0;
117     }
118 }
119
120 always_inline void
121 set_2 (void *a0, void *a1,
122        u64 v0, u64 v1,
123        u64 v_min, u64 v_max,
124        u32 n_bits, u32 is_net_byte_order, u32 is_increment)
125 {
126   ASSERT (v0 >= v_min && v0 <= v_max);
127   ASSERT (v1 >= v_min && v1 <= (v_max + is_increment));
128   if (n_bits == BITS (u8))
129     {
130       ((u8 *) a0)[0] = v0;
131       ((u8 *) a1)[0] = v1;
132     }
133   else if (n_bits == BITS (u16))
134     {
135       if (is_net_byte_order)
136         {
137           v0 = clib_host_to_net_u16 (v0);
138           v1 = clib_host_to_net_u16 (v1);
139         }
140       clib_mem_unaligned (a0, u16) = v0;
141       clib_mem_unaligned (a1, u16) = v1;
142     }
143   else if (n_bits == BITS (u32))
144     {
145       if (is_net_byte_order)
146         {
147           v0 = clib_host_to_net_u32 (v0);
148           v1 = clib_host_to_net_u32 (v1);
149         }
150       clib_mem_unaligned (a0, u32) = v0;
151       clib_mem_unaligned (a1, u32) = v1;
152     }
153   else if (n_bits == BITS (u64))
154     {
155       if (is_net_byte_order)
156         {
157           v0 = clib_host_to_net_u64 (v0);
158           v1 = clib_host_to_net_u64 (v1);
159         }
160       clib_mem_unaligned (a0, u64) = v0;
161       clib_mem_unaligned (a1, u64) = v1;
162     }
163 }
164
165 static_always_inline void
166 do_set_fixed (pg_main_t * pg,
167               pg_stream_t * s,
168               u32 * buffers,
169               u32 n_buffers,
170               u32 n_bits,
171               u32 byte_offset, u32 is_net_byte_order, u64 v_min, u64 v_max)
172 {
173   vlib_main_t *vm = vlib_get_main ();
174
175   while (n_buffers >= 4)
176     {
177       vlib_buffer_t *b0, *b1, *b2, *b3;
178       void *a0, *a1;
179
180       b0 = vlib_get_buffer (vm, buffers[0]);
181       b1 = vlib_get_buffer (vm, buffers[1]);
182       b2 = vlib_get_buffer (vm, buffers[2]);
183       b3 = vlib_get_buffer (vm, buffers[3]);
184       buffers += 2;
185       n_buffers -= 2;
186
187       a0 = (void *) b0 + byte_offset;
188       a1 = (void *) b1 + byte_offset;
189       CLIB_PREFETCH ((void *) b2 + byte_offset, sizeof (v_min), WRITE);
190       CLIB_PREFETCH ((void *) b3 + byte_offset, sizeof (v_min), WRITE);
191
192       set_2 (a0, a1, v_min, v_min, v_min, v_max, n_bits, is_net_byte_order,
193              /* is_increment */ 0);
194
195       ASSERT (validate_buffer_data (b0, s));
196       ASSERT (validate_buffer_data (b1, s));
197     }
198
199   while (n_buffers > 0)
200     {
201       vlib_buffer_t *b0;
202       void *a0;
203
204       b0 = vlib_get_buffer (vm, buffers[0]);
205       buffers += 1;
206       n_buffers -= 1;
207
208       a0 = (void *) b0 + byte_offset;
209
210       set_1 (a0, v_min, v_min, v_max, n_bits, is_net_byte_order);
211
212       ASSERT (validate_buffer_data (b0, s));
213     }
214 }
215
216 static_always_inline u64
217 do_set_increment (pg_main_t * pg,
218                   pg_stream_t * s,
219                   u32 * buffers,
220                   u32 n_buffers,
221                   u32 n_bits,
222                   u32 byte_offset,
223                   u32 is_net_byte_order,
224                   u32 want_sum, u64 * sum_result, u64 v_min, u64 v_max, u64 v)
225 {
226   vlib_main_t *vm = vlib_get_main ();
227   u64 sum = 0;
228
229   ASSERT (v >= v_min && v <= v_max);
230
231   while (n_buffers >= 4)
232     {
233       vlib_buffer_t *b0, *b1, *b2, *b3;
234       void *a0, *a1;
235       u64 v_old;
236
237       b0 = vlib_get_buffer (vm, buffers[0]);
238       b1 = vlib_get_buffer (vm, buffers[1]);
239       b2 = vlib_get_buffer (vm, buffers[2]);
240       b3 = vlib_get_buffer (vm, buffers[3]);
241       buffers += 2;
242       n_buffers -= 2;
243
244       a0 = (void *) b0 + byte_offset;
245       a1 = (void *) b1 + byte_offset;
246       CLIB_PREFETCH ((void *) b2 + byte_offset, sizeof (v_min), WRITE);
247       CLIB_PREFETCH ((void *) b3 + byte_offset, sizeof (v_min), WRITE);
248
249       v_old = v;
250       v = v_old + 2;
251       v = v > v_max ? v_min : v;
252       set_2 (a0, a1,
253              v_old + 0, v_old + 1, v_min, v_max, n_bits, is_net_byte_order,
254              /* is_increment */ 1);
255
256       if (want_sum)
257         sum += 2 * v_old + 1;
258
259       if (PREDICT_FALSE (v_old + 1 > v_max))
260         {
261           if (want_sum)
262             sum -= 2 * v_old + 1;
263
264           v = v_old;
265           set_1 (a0, v + 0, v_min, v_max, n_bits, is_net_byte_order);
266           if (want_sum)
267             sum += v;
268           v += 1;
269
270           v = v > v_max ? v_min : v;
271           set_1 (a1, v + 0, v_min, v_max, n_bits, is_net_byte_order);
272           if (want_sum)
273             sum += v;
274           v += 1;
275         }
276
277       ASSERT (validate_buffer_data (b0, s));
278       ASSERT (validate_buffer_data (b1, s));
279     }
280
281   while (n_buffers > 0)
282     {
283       vlib_buffer_t *b0;
284       void *a0;
285       u64 v_old;
286
287       b0 = vlib_get_buffer (vm, buffers[0]);
288       buffers += 1;
289       n_buffers -= 1;
290
291       a0 = (void *) b0 + byte_offset;
292
293       v_old = v;
294       if (want_sum)
295         sum += v_old;
296       v += 1;
297       v = v > v_max ? v_min : v;
298
299       ASSERT (v_old >= v_min && v_old <= v_max);
300       set_1 (a0, v_old, v_min, v_max, n_bits, is_net_byte_order);
301
302       ASSERT (validate_buffer_data (b0, s));
303     }
304
305   if (want_sum)
306     *sum_result = sum;
307
308   return v;
309 }
310
311 static_always_inline void
312 do_set_random (pg_main_t * pg,
313                pg_stream_t * s,
314                u32 * buffers,
315                u32 n_buffers,
316                u32 n_bits,
317                u32 byte_offset,
318                u32 is_net_byte_order,
319                u32 want_sum, u64 * sum_result, u64 v_min, u64 v_max)
320 {
321   vlib_main_t *vm = vlib_get_main ();
322   u64 v_diff = v_max - v_min + 1;
323   u64 r_mask = max_pow2 (v_diff) - 1;
324   u64 v0, v1;
325   u64 sum = 0;
326   void *random_data;
327
328   random_data = clib_random_buffer_get_data
329     (&vm->random_buffer, n_buffers * n_bits / BITS (u8));
330
331   v0 = v1 = v_min;
332
333   while (n_buffers >= 4)
334     {
335       vlib_buffer_t *b0, *b1, *b2, *b3;
336       void *a0, *a1;
337       u64 r0 = 0, r1 = 0;       /* warnings be gone */
338
339       b0 = vlib_get_buffer (vm, buffers[0]);
340       b1 = vlib_get_buffer (vm, buffers[1]);
341       b2 = vlib_get_buffer (vm, buffers[2]);
342       b3 = vlib_get_buffer (vm, buffers[3]);
343       buffers += 2;
344       n_buffers -= 2;
345
346       a0 = (void *) b0 + byte_offset;
347       a1 = (void *) b1 + byte_offset;
348       CLIB_PREFETCH ((void *) b2 + byte_offset, sizeof (v_min), WRITE);
349       CLIB_PREFETCH ((void *) b3 + byte_offset, sizeof (v_min), WRITE);
350
351       switch (n_bits)
352         {
353 #define _(n)                                    \
354           case BITS (u##n):                     \
355             {                                   \
356               u##n * r = random_data;           \
357               r0 = r[0];                        \
358               r1 = r[1];                        \
359               random_data = r + 2;              \
360             }                                   \
361           break;
362
363           _(8);
364           _(16);
365           _(32);
366           _(64);
367
368 #undef _
369         }
370
371       /* Add power of 2 sized random number which may be out of range. */
372       v0 += r0 & r_mask;
373       v1 += r1 & r_mask;
374
375       /* Twice should be enough to reduce to v_min .. v_max range. */
376       v0 = v0 > v_max ? v0 - v_diff : v0;
377       v1 = v1 > v_max ? v1 - v_diff : v1;
378       v0 = v0 > v_max ? v0 - v_diff : v0;
379       v1 = v1 > v_max ? v1 - v_diff : v1;
380
381       if (want_sum)
382         sum += v0 + v1;
383
384       set_2 (a0, a1, v0, v1, v_min, v_max, n_bits, is_net_byte_order,
385              /* is_increment */ 0);
386
387       ASSERT (validate_buffer_data (b0, s));
388       ASSERT (validate_buffer_data (b1, s));
389     }
390
391   while (n_buffers > 0)
392     {
393       vlib_buffer_t *b0;
394       void *a0;
395       u64 r0 = 0;               /* warnings be gone */
396
397       b0 = vlib_get_buffer (vm, buffers[0]);
398       buffers += 1;
399       n_buffers -= 1;
400
401       a0 = (void *) b0 + byte_offset;
402
403       switch (n_bits)
404         {
405 #define _(n)                                    \
406           case BITS (u##n):                     \
407             {                                   \
408               u##n * r = random_data;           \
409               r0 = r[0];                        \
410               random_data = r + 1;              \
411             }                                   \
412           break;
413
414           _(8);
415           _(16);
416           _(32);
417           _(64);
418
419 #undef _
420         }
421
422       /* Add power of 2 sized random number which may be out of range. */
423       v0 += r0 & r_mask;
424
425       /* Twice should be enough to reduce to v_min .. v_max range. */
426       v0 = v0 > v_max ? v0 - v_diff : v0;
427       v0 = v0 > v_max ? v0 - v_diff : v0;
428
429       if (want_sum)
430         sum += v0;
431
432       set_1 (a0, v0, v_min, v_max, n_bits, is_net_byte_order);
433
434       ASSERT (validate_buffer_data (b0, s));
435     }
436
437   if (want_sum)
438     *sum_result = sum;
439 }
440
441 #define _(i,t)                                                  \
442   clib_mem_unaligned (a##i, t) =                                \
443     clib_host_to_net_##t ((clib_net_to_host_mem_##t (a##i) &~ mask)     \
444                           | (v##i << shift))
445
446 always_inline void
447 setbits_1 (void *a0,
448            u64 v0,
449            u64 v_min, u64 v_max,
450            u32 max_bits, u32 n_bits, u64 mask, u32 shift)
451 {
452   ASSERT (v0 >= v_min && v0 <= v_max);
453   if (max_bits == BITS (u8))
454     ((u8 *) a0)[0] = (((u8 *) a0)[0] & ~mask) | (v0 << shift);
455
456   else if (max_bits == BITS (u16))
457     {
458       _(0, u16);
459     }
460   else if (max_bits == BITS (u32))
461     {
462       _(0, u32);
463     }
464   else if (max_bits == BITS (u64))
465     {
466       _(0, u64);
467     }
468 }
469
470 always_inline void
471 setbits_2 (void *a0, void *a1,
472            u64 v0, u64 v1,
473            u64 v_min, u64 v_max,
474            u32 max_bits, u32 n_bits, u64 mask, u32 shift, u32 is_increment)
475 {
476   ASSERT (v0 >= v_min && v0 <= v_max);
477   ASSERT (v1 >= v_min && v1 <= v_max + is_increment);
478   if (max_bits == BITS (u8))
479     {
480       ((u8 *) a0)[0] = (((u8 *) a0)[0] & ~mask) | (v0 << shift);
481       ((u8 *) a1)[0] = (((u8 *) a1)[0] & ~mask) | (v1 << shift);
482     }
483
484   else if (max_bits == BITS (u16))
485     {
486       _(0, u16);
487       _(1, u16);
488     }
489   else if (max_bits == BITS (u32))
490     {
491       _(0, u32);
492       _(1, u32);
493     }
494   else if (max_bits == BITS (u64))
495     {
496       _(0, u64);
497       _(1, u64);
498     }
499 }
500
501 #undef _
502
503 static_always_inline void
504 do_setbits_fixed (pg_main_t * pg,
505                   pg_stream_t * s,
506                   u32 * buffers,
507                   u32 n_buffers,
508                   u32 max_bits,
509                   u32 n_bits,
510                   u32 byte_offset, u64 v_min, u64 v_max, u64 mask, u32 shift)
511 {
512   vlib_main_t *vm = vlib_get_main ();
513
514   while (n_buffers >= 4)
515     {
516       vlib_buffer_t *b0, *b1, *b2, *b3;
517       void *a0, *a1;
518
519       b0 = vlib_get_buffer (vm, buffers[0]);
520       b1 = vlib_get_buffer (vm, buffers[1]);
521       b2 = vlib_get_buffer (vm, buffers[2]);
522       b3 = vlib_get_buffer (vm, buffers[3]);
523       buffers += 2;
524       n_buffers -= 2;
525
526       a0 = (void *) b0 + byte_offset;
527       a1 = (void *) b1 + byte_offset;
528       CLIB_PREFETCH ((void *) b2 + byte_offset, sizeof (v_min), WRITE);
529       CLIB_PREFETCH ((void *) b3 + byte_offset, sizeof (v_min), WRITE);
530
531       setbits_2 (a0, a1,
532                  v_min, v_min, v_min, v_max, max_bits, n_bits, mask, shift,
533                  /* is_increment */ 0);
534
535       ASSERT (validate_buffer_data (b0, s));
536       ASSERT (validate_buffer_data (b1, s));
537     }
538
539   while (n_buffers > 0)
540     {
541       vlib_buffer_t *b0;
542       void *a0;
543
544       b0 = vlib_get_buffer (vm, buffers[0]);
545       buffers += 1;
546       n_buffers -= 1;
547
548       a0 = (void *) b0 + byte_offset;
549
550       setbits_1 (a0, v_min, v_min, v_max, max_bits, n_bits, mask, shift);
551       ASSERT (validate_buffer_data (b0, s));
552     }
553 }
554
555 static_always_inline u64
556 do_setbits_increment (pg_main_t * pg,
557                       pg_stream_t * s,
558                       u32 * buffers,
559                       u32 n_buffers,
560                       u32 max_bits,
561                       u32 n_bits,
562                       u32 byte_offset,
563                       u64 v_min, u64 v_max, u64 v, u64 mask, u32 shift)
564 {
565   vlib_main_t *vm = vlib_get_main ();
566
567   ASSERT (v >= v_min && v <= v_max);
568
569   while (n_buffers >= 4)
570     {
571       vlib_buffer_t *b0, *b1, *b2, *b3;
572       void *a0, *a1;
573       u64 v_old;
574
575       b0 = vlib_get_buffer (vm, buffers[0]);
576       b1 = vlib_get_buffer (vm, buffers[1]);
577       b2 = vlib_get_buffer (vm, buffers[2]);
578       b3 = vlib_get_buffer (vm, buffers[3]);
579       buffers += 2;
580       n_buffers -= 2;
581
582       a0 = (void *) b0 + byte_offset;
583       a1 = (void *) b1 + byte_offset;
584       CLIB_PREFETCH ((void *) b2 + byte_offset, sizeof (v_min), WRITE);
585       CLIB_PREFETCH ((void *) b3 + byte_offset, sizeof (v_min), WRITE);
586
587       v_old = v;
588       v = v_old + 2;
589       v = v > v_max ? v_min : v;
590       setbits_2 (a0, a1,
591                  v_old + 0, v_old + 1,
592                  v_min, v_max, max_bits, n_bits, mask, shift,
593                  /* is_increment */ 1);
594
595       if (PREDICT_FALSE (v_old + 1 > v_max))
596         {
597           v = v_old;
598           setbits_1 (a0, v + 0, v_min, v_max, max_bits, n_bits, mask, shift);
599           v += 1;
600
601           v = v > v_max ? v_min : v;
602           setbits_1 (a1, v + 0, v_min, v_max, max_bits, n_bits, mask, shift);
603           v += 1;
604         }
605       ASSERT (validate_buffer_data (b0, s));
606       ASSERT (validate_buffer_data (b1, s));
607     }
608
609   while (n_buffers > 0)
610     {
611       vlib_buffer_t *b0;
612       void *a0;
613       u64 v_old;
614
615       b0 = vlib_get_buffer (vm, buffers[0]);
616       buffers += 1;
617       n_buffers -= 1;
618
619       a0 = (void *) b0 + byte_offset;
620
621       v_old = v;
622       v = v_old + 1;
623       v = v > v_max ? v_min : v;
624
625       ASSERT (v_old >= v_min && v_old <= v_max);
626       setbits_1 (a0, v_old, v_min, v_max, max_bits, n_bits, mask, shift);
627
628       ASSERT (validate_buffer_data (b0, s));
629     }
630
631   return v;
632 }
633
634 static_always_inline void
635 do_setbits_random (pg_main_t * pg,
636                    pg_stream_t * s,
637                    u32 * buffers,
638                    u32 n_buffers,
639                    u32 max_bits,
640                    u32 n_bits,
641                    u32 byte_offset, u64 v_min, u64 v_max, u64 mask, u32 shift)
642 {
643   vlib_main_t *vm = vlib_get_main ();
644   u64 v_diff = v_max - v_min + 1;
645   u64 r_mask = max_pow2 (v_diff) - 1;
646   u64 v0, v1;
647   void *random_data;
648
649   random_data = clib_random_buffer_get_data
650     (&vm->random_buffer, n_buffers * max_bits / BITS (u8));
651   v0 = v1 = v_min;
652
653   while (n_buffers >= 4)
654     {
655       vlib_buffer_t *b0, *b1, *b2, *b3;
656       void *a0, *a1;
657       u64 r0 = 0, r1 = 0;       /* warnings be gone */
658
659       b0 = vlib_get_buffer (vm, buffers[0]);
660       b1 = vlib_get_buffer (vm, buffers[1]);
661       b2 = vlib_get_buffer (vm, buffers[2]);
662       b3 = vlib_get_buffer (vm, buffers[3]);
663       buffers += 2;
664       n_buffers -= 2;
665
666       a0 = (void *) b0 + byte_offset;
667       a1 = (void *) b1 + byte_offset;
668       CLIB_PREFETCH ((void *) b2 + byte_offset, sizeof (v_min), WRITE);
669       CLIB_PREFETCH ((void *) b3 + byte_offset, sizeof (v_min), WRITE);
670
671       switch (max_bits)
672         {
673 #define _(n)                                    \
674           case BITS (u##n):                     \
675             {                                   \
676               u##n * r = random_data;           \
677               r0 = r[0];                        \
678               r1 = r[1];                        \
679               random_data = r + 2;              \
680             }                                   \
681           break;
682
683           _(8);
684           _(16);
685           _(32);
686           _(64);
687
688 #undef _
689         }
690
691       /* Add power of 2 sized random number which may be out of range. */
692       v0 += r0 & r_mask;
693       v1 += r1 & r_mask;
694
695       /* Twice should be enough to reduce to v_min .. v_max range. */
696       v0 = v0 > v_max ? v0 - v_diff : v0;
697       v1 = v1 > v_max ? v1 - v_diff : v1;
698       v0 = v0 > v_max ? v0 - v_diff : v0;
699       v1 = v1 > v_max ? v1 - v_diff : v1;
700
701       setbits_2 (a0, a1, v0, v1, v_min, v_max, max_bits, n_bits, mask, shift,
702                  /* is_increment */ 0);
703
704       ASSERT (validate_buffer_data (b0, s));
705       ASSERT (validate_buffer_data (b1, s));
706     }
707
708   while (n_buffers > 0)
709     {
710       vlib_buffer_t *b0;
711       void *a0;
712       u64 r0 = 0;               /* warnings be gone */
713
714       b0 = vlib_get_buffer (vm, buffers[0]);
715       buffers += 1;
716       n_buffers -= 1;
717
718       a0 = (void *) b0 + byte_offset;
719
720       switch (max_bits)
721         {
722 #define _(n)                                    \
723           case BITS (u##n):                     \
724             {                                   \
725               u##n * r = random_data;           \
726               r0 = r[0];                        \
727               random_data = r + 1;              \
728             }                                   \
729           break;
730
731           _(8);
732           _(16);
733           _(32);
734           _(64);
735
736 #undef _
737         }
738
739       /* Add power of 2 sized random number which may be out of range. */
740       v0 += r0 & r_mask;
741
742       /* Twice should be enough to reduce to v_min .. v_max range. */
743       v0 = v0 > v_max ? v0 - v_diff : v0;
744       v0 = v0 > v_max ? v0 - v_diff : v0;
745
746       setbits_1 (a0, v0, v_min, v_max, max_bits, n_bits, mask, shift);
747
748       ASSERT (validate_buffer_data (b0, s));
749     }
750 }
751
752 static u64
753 do_it (pg_main_t * pg,
754        pg_stream_t * s,
755        u32 * buffers,
756        u32 n_buffers,
757        u32 lo_bit, u32 hi_bit,
758        u64 v_min, u64 v_max, u64 v, pg_edit_type_t edit_type)
759 {
760   u32 max_bits, l0, l1, h1, start_bit;
761
762   if (v_min == v_max)
763     edit_type = PG_EDIT_FIXED;
764
765   l0 = lo_bit / BITS (u8);
766   l1 = lo_bit % BITS (u8);
767   h1 = hi_bit % BITS (u8);
768
769   start_bit = l0 * BITS (u8);
770
771   max_bits = hi_bit - start_bit;
772   ASSERT (max_bits <= 64);
773
774 #define _(n)                                            \
775   case (n):                                             \
776     if (edit_type == PG_EDIT_INCREMENT)                 \
777       v = do_set_increment (pg, s, buffers, n_buffers,  \
778                             BITS (u##n),                \
779                             l0,                         \
780                             /* is_net_byte_order */ 1,  \
781                             /* want sum */ 0, 0,        \
782                             v_min, v_max,               \
783                             v);                         \
784     else if (edit_type == PG_EDIT_RANDOM)               \
785       do_set_random (pg, s, buffers, n_buffers,         \
786                      BITS (u##n),                       \
787                      l0,                                \
788                      /* is_net_byte_order */ 1,         \
789                      /* want sum */ 0, 0,               \
790                      v_min, v_max);                     \
791     else /* edit_type == PG_EDIT_FIXED */               \
792       do_set_fixed (pg, s, buffers, n_buffers,          \
793                     BITS (u##n),                        \
794                     l0,                                 \
795                     /* is_net_byte_order */ 1,          \
796                     v_min, v_max);                      \
797   goto done;
798
799   if (l1 == 0 && h1 == 0)
800     {
801       switch (max_bits)
802         {
803           _(8);
804           _(16);
805           _(32);
806           _(64);
807         }
808     }
809
810 #undef _
811
812   {
813     u64 mask;
814     u32 shift = l1;
815     u32 n_bits = max_bits;
816
817     max_bits = clib_max (max_pow2 (n_bits), 8);
818
819     mask = ((u64) 1 << (u64) n_bits) - 1;
820     mask &= ~(((u64) 1 << (u64) shift) - 1);
821
822     mask <<= max_bits - n_bits;
823     shift += max_bits - n_bits;
824
825     switch (max_bits)
826       {
827 #define _(n)                                                            \
828         case (n):                                                       \
829           if (edit_type == PG_EDIT_INCREMENT)                           \
830             v = do_setbits_increment (pg, s, buffers, n_buffers,        \
831                                       BITS (u##n), n_bits,              \
832                                       l0, v_min, v_max, v,              \
833                                       mask, shift);                     \
834           else if (edit_type == PG_EDIT_RANDOM)                         \
835             do_setbits_random (pg, s, buffers, n_buffers,               \
836                                BITS (u##n), n_bits,                     \
837                                l0, v_min, v_max,                        \
838                                mask, shift);                            \
839           else /* edit_type == PG_EDIT_FIXED */                         \
840             do_setbits_fixed (pg, s, buffers, n_buffers,                \
841                               BITS (u##n), n_bits,                      \
842                               l0, v_min, v_max,                         \
843                               mask, shift);                             \
844         goto done;
845
846         _(8);
847         _(16);
848         _(32);
849         _(64);
850
851 #undef _
852       }
853   }
854
855 done:
856   return v;
857 }
858
859 static void
860 pg_generate_set_lengths (pg_main_t * pg,
861                          pg_stream_t * s, u32 * buffers, u32 n_buffers)
862 {
863   u64 v_min, v_max, length_sum;
864   pg_edit_type_t edit_type;
865
866   v_min = s->min_packet_bytes;
867   v_max = s->max_packet_bytes;
868   edit_type = s->packet_size_edit_type;
869
870   if (edit_type == PG_EDIT_INCREMENT)
871     s->last_increment_packet_size
872       = do_set_increment (pg, s, buffers, n_buffers,
873                           8 * STRUCT_SIZE_OF (vlib_buffer_t, current_length),
874                           STRUCT_OFFSET_OF (vlib_buffer_t, current_length),
875                           /* is_net_byte_order */ 0,
876                           /* want sum */ 1, &length_sum,
877                           v_min, v_max, s->last_increment_packet_size);
878
879   else if (edit_type == PG_EDIT_RANDOM)
880     do_set_random (pg, s, buffers, n_buffers,
881                    8 * STRUCT_SIZE_OF (vlib_buffer_t, current_length),
882                    STRUCT_OFFSET_OF (vlib_buffer_t, current_length),
883                    /* is_net_byte_order */ 0,
884                    /* want sum */ 1, &length_sum,
885                    v_min, v_max);
886
887   else                          /* edit_type == PG_EDIT_FIXED */
888     {
889       do_set_fixed (pg, s, buffers, n_buffers,
890                     8 * STRUCT_SIZE_OF (vlib_buffer_t, current_length),
891                     STRUCT_OFFSET_OF (vlib_buffer_t, current_length),
892                     /* is_net_byte_order */ 0,
893                     v_min, v_max);
894       length_sum = v_min * n_buffers;
895     }
896
897   {
898     vnet_main_t *vnm = vnet_get_main ();
899     vnet_interface_main_t *im = &vnm->interface_main;
900     vnet_sw_interface_t *si =
901       vnet_get_sw_interface (vnm, s->sw_if_index[VLIB_RX]);
902
903     vlib_increment_combined_counter (im->combined_sw_if_counters
904                                      + VNET_INTERFACE_COUNTER_RX,
905                                      vlib_get_thread_index (),
906                                      si->sw_if_index, n_buffers, length_sum);
907   }
908
909 }
910
911 static void
912 pg_generate_fix_multi_buffer_lengths (pg_main_t * pg,
913                                       pg_stream_t * s,
914                                       u32 * buffers, u32 n_buffers)
915 {
916   vlib_main_t *vm = vlib_get_main ();
917   pg_buffer_index_t *pbi;
918   uword n_bytes_left;
919   static u32 *unused_buffers = 0;
920
921   while (n_buffers > 0)
922     {
923       vlib_buffer_t *b;
924       u32 bi;
925
926       bi = buffers[0];
927       b = vlib_get_buffer (vm, bi);
928
929       /* Current length here is length of whole packet. */
930       n_bytes_left = b->current_length;
931
932       pbi = s->buffer_indices;
933       while (1)
934         {
935           uword n = clib_min (n_bytes_left, s->buffer_bytes);
936
937           b->current_length = n;
938           n_bytes_left -= n;
939           if (n_bytes_left > 0)
940             b->flags |= VLIB_BUFFER_NEXT_PRESENT;
941           else
942             b->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
943
944           /* Return unused buffers to fifos. */
945           if (n == 0)
946             vec_add1 (unused_buffers, bi);
947
948           pbi++;
949           if (pbi >= vec_end (s->buffer_indices))
950             break;
951
952           bi = b->next_buffer;
953           b = vlib_get_buffer (vm, bi);
954         }
955       ASSERT (n_bytes_left == 0);
956
957       buffers += 1;
958       n_buffers -= 1;
959     }
960
961   if (vec_len (unused_buffers) > 0)
962     {
963       vlib_buffer_free_no_next (vm, unused_buffers, vec_len (unused_buffers));
964       _vec_len (unused_buffers) = 0;
965     }
966 }
967
968 static void
969 pg_generate_edit (pg_main_t * pg,
970                   pg_stream_t * s, u32 * buffers, u32 n_buffers)
971 {
972   pg_edit_t *e;
973
974   vec_foreach (e, s->non_fixed_edits)
975   {
976     switch (e->type)
977       {
978       case PG_EDIT_RANDOM:
979       case PG_EDIT_INCREMENT:
980         {
981           u32 lo_bit, hi_bit;
982           u64 v_min, v_max;
983
984           v_min = pg_edit_get_value (e, PG_EDIT_LO);
985           v_max = pg_edit_get_value (e, PG_EDIT_HI);
986
987           hi_bit = (BITS (u8) * STRUCT_OFFSET_OF (vlib_buffer_t, data)
988                     + BITS (u8) + e->lsb_bit_offset);
989           lo_bit = hi_bit - e->n_bits;
990
991           e->last_increment_value
992             = do_it (pg, s, buffers, n_buffers, lo_bit, hi_bit, v_min, v_max,
993                      e->last_increment_value, e->type);
994         }
995         break;
996
997       case PG_EDIT_UNSPECIFIED:
998         break;
999
1000       default:
1001         /* Should not be any fixed edits left. */
1002         ASSERT (0);
1003         break;
1004       }
1005   }
1006
1007   /* Call any edit functions to e.g. completely IP lengths, checksums, ... */
1008   {
1009     int i;
1010     for (i = vec_len (s->edit_groups) - 1; i >= 0; i--)
1011       {
1012         pg_edit_group_t *g = s->edit_groups + i;
1013         if (g->edit_function)
1014           g->edit_function (pg, s, g, buffers, n_buffers);
1015       }
1016   }
1017 }
1018
1019 static void
1020 pg_set_next_buffer_pointers (pg_main_t * pg,
1021                              pg_stream_t * s,
1022                              u32 * buffers, u32 * next_buffers, u32 n_buffers)
1023 {
1024   vlib_main_t *vm = vlib_get_main ();
1025
1026   while (n_buffers >= 4)
1027     {
1028       u32 ni0, ni1;
1029       vlib_buffer_t *b0, *b1;
1030
1031       b0 = vlib_get_buffer (vm, buffers[0]);
1032       b1 = vlib_get_buffer (vm, buffers[1]);
1033       ni0 = next_buffers[0];
1034       ni1 = next_buffers[1];
1035
1036       vlib_prefetch_buffer_with_index (vm, buffers[2], WRITE);
1037       vlib_prefetch_buffer_with_index (vm, buffers[3], WRITE);
1038
1039       b0->flags |= VLIB_BUFFER_NEXT_PRESENT;
1040       b1->flags |= VLIB_BUFFER_NEXT_PRESENT;
1041       b0->next_buffer = ni0;
1042       b1->next_buffer = ni1;
1043
1044       buffers += 2;
1045       next_buffers += 2;
1046       n_buffers -= 2;
1047     }
1048
1049   while (n_buffers > 0)
1050     {
1051       u32 ni0;
1052       vlib_buffer_t *b0;
1053
1054       b0 = vlib_get_buffer (vm, buffers[0]);
1055       ni0 = next_buffers[0];
1056       buffers += 1;
1057       next_buffers += 1;
1058       n_buffers -= 1;
1059
1060       b0->flags |= VLIB_BUFFER_NEXT_PRESENT;
1061       b0->next_buffer = ni0;
1062     }
1063 }
1064
1065 static_always_inline void
1066 init_buffers_inline (vlib_main_t * vm,
1067                      pg_stream_t * s,
1068                      u32 * buffers,
1069                      u32 n_buffers, u32 data_offset, u32 n_data, u32 set_data)
1070 {
1071   u32 n_left, *b;
1072   u8 *data, *mask;
1073
1074   ASSERT (s->replay_packet_templates == 0);
1075
1076   data = s->fixed_packet_data + data_offset;
1077   mask = s->fixed_packet_data_mask + data_offset;
1078   if (data + n_data >= vec_end (s->fixed_packet_data))
1079     n_data = (data < vec_end (s->fixed_packet_data)
1080               ? vec_end (s->fixed_packet_data) - data : 0);
1081   if (n_data > 0)
1082     {
1083       ASSERT (data + n_data <= vec_end (s->fixed_packet_data));
1084       ASSERT (mask + n_data <= vec_end (s->fixed_packet_data_mask));
1085     }
1086
1087   n_left = n_buffers;
1088   b = buffers;
1089
1090   while (n_left >= 4)
1091     {
1092       u32 bi0, bi1;
1093       vlib_buffer_t *b0, *b1;
1094
1095       /* Prefetch next iteration. */
1096       vlib_prefetch_buffer_with_index (vm, b[2], STORE);
1097       vlib_prefetch_buffer_with_index (vm, b[3], STORE);
1098
1099       bi0 = b[0];
1100       bi1 = b[1];
1101       b += 2;
1102       n_left -= 2;
1103
1104       b0 = vlib_get_buffer (vm, bi0);
1105       b1 = vlib_get_buffer (vm, bi1);
1106
1107       vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1108         vnet_buffer (b1)->sw_if_index[VLIB_RX] = s->sw_if_index[VLIB_RX];
1109
1110       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1111         vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1112
1113       if (set_data)
1114         {
1115           clib_memcpy_fast (b0->data, data, n_data);
1116           clib_memcpy_fast (b1->data, data, n_data);
1117         }
1118       else
1119         {
1120           ASSERT (validate_buffer_data2 (b0, s, data_offset, n_data));
1121           ASSERT (validate_buffer_data2 (b1, s, data_offset, n_data));
1122         }
1123     }
1124
1125   while (n_left >= 1)
1126     {
1127       u32 bi0;
1128       vlib_buffer_t *b0;
1129
1130       bi0 = b[0];
1131       b += 1;
1132       n_left -= 1;
1133
1134       b0 = vlib_get_buffer (vm, bi0);
1135       vnet_buffer (b0)->sw_if_index[VLIB_RX] = s->sw_if_index[VLIB_RX];
1136       /* s->sw_if_index[VLIB_TX]; */
1137       vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1138
1139       if (set_data)
1140         clib_memcpy_fast (b0->data, data, n_data);
1141       else
1142         ASSERT (validate_buffer_data2 (b0, s, data_offset, n_data));
1143     }
1144 }
1145
1146 static u32
1147 pg_stream_fill_helper (pg_main_t * pg,
1148                        pg_stream_t * s,
1149                        pg_buffer_index_t * bi,
1150                        u32 * buffers, u32 * next_buffers, u32 n_alloc)
1151 {
1152   vlib_main_t *vm = vlib_get_main ();
1153   uword is_start_of_packet = bi == s->buffer_indices;
1154   u32 n_allocated;
1155
1156   ASSERT (vec_len (s->replay_packet_templates) == 0);
1157
1158   n_allocated = vlib_buffer_alloc (vm, buffers, n_alloc);
1159   if (n_allocated == 0)
1160     return 0;
1161
1162   /*
1163    * We can't assume we got all the buffers we asked for...
1164    * This never worked until recently.
1165    */
1166   n_alloc = n_allocated;
1167
1168   /* Reinitialize buffers */
1169   init_buffers_inline
1170     (vm, s,
1171      buffers,
1172      n_alloc, (bi - s->buffer_indices) * s->buffer_bytes /* data offset */ ,
1173      s->buffer_bytes,
1174      /* set_data */ 1);
1175
1176   if (next_buffers)
1177     pg_set_next_buffer_pointers (pg, s, buffers, next_buffers, n_alloc);
1178
1179   if (is_start_of_packet)
1180     {
1181       pg_generate_set_lengths (pg, s, buffers, n_alloc);
1182       if (vec_len (s->buffer_indices) > 1)
1183         pg_generate_fix_multi_buffer_lengths (pg, s, buffers, n_alloc);
1184
1185       pg_generate_edit (pg, s, buffers, n_alloc);
1186     }
1187
1188   return n_alloc;
1189 }
1190
1191 static u32
1192 pg_stream_fill_replay (pg_main_t * pg, pg_stream_t * s, u32 n_alloc)
1193 {
1194   pg_buffer_index_t *bi;
1195   u32 n_left, i, l;
1196   u32 buffer_alloc_request = 0;
1197   u32 buffer_alloc_result;
1198   u32 current_buffer_index;
1199   u32 *buffers;
1200   vlib_main_t *vm = vlib_get_main ();
1201   vnet_main_t *vnm = vnet_get_main ();
1202   vnet_interface_main_t *im = &vnm->interface_main;
1203   vnet_sw_interface_t *si;
1204
1205   buffers = pg->replay_buffers_by_thread[vm->thread_index];
1206   vec_reset_length (buffers);
1207   bi = s->buffer_indices;
1208
1209   n_left = n_alloc;
1210   i = s->current_replay_packet_index;
1211   l = vec_len (s->replay_packet_templates);
1212
1213   /* Figure out how many buffers we need */
1214   while (n_left > 0)
1215     {
1216       u8 *d0;
1217
1218       d0 = vec_elt (s->replay_packet_templates, i);
1219       buffer_alloc_request += (vec_len (d0) + (VLIB_BUFFER_DATA_SIZE - 1))
1220         / VLIB_BUFFER_DATA_SIZE;
1221
1222       i = ((i + 1) == l) ? 0 : i + 1;
1223       n_left--;
1224     }
1225
1226   ASSERT (buffer_alloc_request > 0);
1227   vec_validate (buffers, buffer_alloc_request - 1);
1228
1229   /* Allocate that many buffers */
1230   buffer_alloc_result = vlib_buffer_alloc (vm, buffers, buffer_alloc_request);
1231   if (buffer_alloc_result < buffer_alloc_request)
1232     {
1233       clib_warning ("alloc failure, got %d not %d", buffer_alloc_result,
1234                     buffer_alloc_request);
1235       vlib_buffer_free_no_next (vm, buffers, buffer_alloc_result);
1236       pg->replay_buffers_by_thread[vm->thread_index] = buffers;
1237       return 0;
1238     }
1239
1240   /* Now go generate the buffers, and add them to the FIFO */
1241   n_left = n_alloc;
1242
1243   current_buffer_index = 0;
1244   i = s->current_replay_packet_index;
1245   l = vec_len (s->replay_packet_templates);
1246   while (n_left > 0)
1247     {
1248       u8 *d0;
1249       int not_last;
1250       u32 data_offset;
1251       u32 bytes_to_copy, bytes_this_chunk;
1252       vlib_buffer_t *b;
1253
1254       d0 = vec_elt (s->replay_packet_templates, i);
1255       data_offset = 0;
1256       bytes_to_copy = vec_len (d0);
1257
1258       /* Add head chunk to pg fifo */
1259       clib_fifo_add1 (bi->buffer_fifo, buffers[current_buffer_index]);
1260
1261       /* Copy the data */
1262       while (bytes_to_copy)
1263         {
1264           bytes_this_chunk = clib_min (bytes_to_copy, VLIB_BUFFER_DATA_SIZE);
1265           ASSERT (current_buffer_index < vec_len (buffers));
1266           b = vlib_get_buffer (vm, buffers[current_buffer_index]);
1267           clib_memcpy_fast (b->data, d0 + data_offset, bytes_this_chunk);
1268           vnet_buffer (b)->sw_if_index[VLIB_RX] = s->sw_if_index[VLIB_RX];
1269           vnet_buffer (b)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1270           b->flags = 0;
1271           b->next_buffer = 0;
1272           b->current_data = 0;
1273           b->current_length = bytes_this_chunk;
1274
1275           not_last = bytes_this_chunk < bytes_to_copy;
1276           if (not_last)
1277             {
1278               ASSERT (current_buffer_index < (vec_len (buffers) - 1));
1279               b->flags |= VLIB_BUFFER_NEXT_PRESENT;
1280               b->next_buffer = buffers[current_buffer_index + 1];
1281             }
1282           bytes_to_copy -= bytes_this_chunk;
1283           data_offset += bytes_this_chunk;
1284           current_buffer_index++;
1285         }
1286
1287       i = ((i + 1) == l) ? 0 : i + 1;
1288       n_left--;
1289     }
1290
1291   /* Update the interface counters */
1292   si = vnet_get_sw_interface (vnm, s->sw_if_index[VLIB_RX]);
1293   l = 0;
1294   for (i = 0; i < n_alloc; i++)
1295     l += vlib_buffer_index_length_in_chain (vm, buffers[i]);
1296   vlib_increment_combined_counter (im->combined_sw_if_counters
1297                                    + VNET_INTERFACE_COUNTER_RX,
1298                                    vlib_get_thread_index (),
1299                                    si->sw_if_index, n_alloc, l);
1300
1301   s->current_replay_packet_index += n_alloc;
1302   s->current_replay_packet_index %= vec_len (s->replay_packet_templates);
1303
1304   pg->replay_buffers_by_thread[vm->thread_index] = buffers;
1305   return n_alloc;
1306 }
1307
1308
1309 static u32
1310 pg_stream_fill (pg_main_t * pg, pg_stream_t * s, u32 n_buffers)
1311 {
1312   pg_buffer_index_t *bi;
1313   word i, n_in_fifo, n_alloc, n_free, n_added;
1314   u32 *tail, *start, *end, *last_tail, *last_start;
1315
1316   bi = s->buffer_indices;
1317
1318   n_in_fifo = clib_fifo_elts (bi->buffer_fifo);
1319   if (n_in_fifo >= n_buffers)
1320     return n_in_fifo;
1321
1322   n_alloc = n_buffers - n_in_fifo;
1323
1324   /* Round up, but never generate more than limit. */
1325   n_alloc = clib_max (VLIB_FRAME_SIZE, n_alloc);
1326
1327   if (s->n_packets_limit > 0
1328       && s->n_packets_generated + n_in_fifo + n_alloc >= s->n_packets_limit)
1329     {
1330       n_alloc = s->n_packets_limit - s->n_packets_generated - n_in_fifo;
1331       if (n_alloc < 0)
1332         n_alloc = 0;
1333     }
1334
1335   /*
1336    * Handle pcap replay directly
1337    */
1338   if (s->replay_packet_templates)
1339     return pg_stream_fill_replay (pg, s, n_alloc);
1340
1341   /* All buffer fifos should have the same size. */
1342   if (CLIB_DEBUG > 0)
1343     {
1344       uword l = ~0, e;
1345       vec_foreach (bi, s->buffer_indices)
1346       {
1347         e = clib_fifo_elts (bi->buffer_fifo);
1348         if (bi == s->buffer_indices)
1349           l = e;
1350         ASSERT (l == e);
1351       }
1352     }
1353
1354   last_tail = last_start = 0;
1355   n_added = n_alloc;
1356
1357   for (i = vec_len (s->buffer_indices) - 1; i >= 0; i--)
1358     {
1359       bi = vec_elt_at_index (s->buffer_indices, i);
1360
1361       n_free = clib_fifo_free_elts (bi->buffer_fifo);
1362       if (n_free < n_alloc)
1363         clib_fifo_resize (bi->buffer_fifo, n_alloc - n_free);
1364
1365       tail = clib_fifo_advance_tail (bi->buffer_fifo, n_alloc);
1366       start = bi->buffer_fifo;
1367       end = clib_fifo_end (bi->buffer_fifo);
1368
1369       if (tail + n_alloc <= end)
1370         {
1371           n_added =
1372             pg_stream_fill_helper (pg, s, bi, tail, last_tail, n_alloc);
1373         }
1374       else
1375         {
1376           u32 n = clib_min (end - tail, n_alloc);
1377           n_added = pg_stream_fill_helper (pg, s, bi, tail, last_tail, n);
1378
1379           if (n_added == n && n_alloc > n_added)
1380             {
1381               n_added += pg_stream_fill_helper
1382                 (pg, s, bi, start, last_start, n_alloc - n_added);
1383             }
1384         }
1385
1386       if (PREDICT_FALSE (n_added < n_alloc))
1387         tail = clib_fifo_advance_tail (bi->buffer_fifo, n_added - n_alloc);
1388
1389       last_tail = tail;
1390       last_start = start;
1391
1392       /* Verify that pkts in the fifo are properly allocated */
1393     }
1394
1395   return n_in_fifo + n_added;
1396 }
1397
1398 typedef struct
1399 {
1400   u32 stream_index;
1401
1402   u32 packet_length;
1403   u32 sw_if_index;
1404
1405   /* Use pre data for packet data. */
1406   vlib_buffer_t buffer;
1407 } pg_input_trace_t;
1408
1409 static u8 *
1410 format_pg_input_trace (u8 * s, va_list * va)
1411 {
1412   vlib_main_t *vm = va_arg (*va, vlib_main_t *);
1413   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
1414   pg_input_trace_t *t = va_arg (*va, pg_input_trace_t *);
1415   pg_main_t *pg = &pg_main;
1416   pg_stream_t *stream;
1417   vlib_node_t *n;
1418   u32 indent = format_get_indent (s);
1419
1420   stream = 0;
1421   if (!pool_is_free_index (pg->streams, t->stream_index))
1422     stream = pool_elt_at_index (pg->streams, t->stream_index);
1423
1424   if (stream)
1425     s = format (s, "stream %v", pg->streams[t->stream_index].name);
1426   else
1427     s = format (s, "stream %d", t->stream_index);
1428
1429   s = format (s, ", %d bytes", t->packet_length);
1430   s = format (s, ", %d sw_if_index", t->sw_if_index);
1431
1432   s = format (s, "\n%U%U",
1433               format_white_space, indent, format_vnet_buffer, &t->buffer);
1434
1435   s = format (s, "\n%U", format_white_space, indent);
1436
1437   n = 0;
1438   if (stream)
1439     n = vlib_get_node (vm, stream->node_index);
1440
1441   if (n && n->format_buffer)
1442     s = format (s, "%U", n->format_buffer,
1443                 t->buffer.pre_data, sizeof (t->buffer.pre_data));
1444   else
1445     s = format (s, "%U",
1446                 format_hex_bytes, t->buffer.pre_data,
1447                 ARRAY_LEN (t->buffer.pre_data));
1448   return s;
1449 }
1450
1451 static void
1452 pg_input_trace (pg_main_t * pg,
1453                 vlib_node_runtime_t * node,
1454                 pg_stream_t * s, u32 * buffers, u32 n_buffers)
1455 {
1456   vlib_main_t *vm = vlib_get_main ();
1457   u32 *b, n_left, stream_index, next_index;
1458
1459   n_left = n_buffers;
1460   b = buffers;
1461   stream_index = s - pg->streams;
1462   next_index = s->next_index;
1463
1464   while (n_left >= 2)
1465     {
1466       u32 bi0, bi1;
1467       vlib_buffer_t *b0, *b1;
1468       pg_input_trace_t *t0, *t1;
1469
1470       bi0 = b[0];
1471       bi1 = b[1];
1472       b += 2;
1473       n_left -= 2;
1474
1475       b0 = vlib_get_buffer (vm, bi0);
1476       b1 = vlib_get_buffer (vm, bi1);
1477
1478       vlib_trace_buffer (vm, node, next_index, b0, /* follow_chain */ 1);
1479       vlib_trace_buffer (vm, node, next_index, b1, /* follow_chain */ 1);
1480
1481       t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1482       t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
1483
1484       t0->stream_index = stream_index;
1485       t1->stream_index = stream_index;
1486
1487       t0->packet_length = vlib_buffer_length_in_chain (vm, b0);
1488       t1->packet_length = vlib_buffer_length_in_chain (vm, b1);
1489
1490       t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1491       t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1492
1493       clib_memcpy_fast (&t0->buffer, b0,
1494                         sizeof (b0[0]) - sizeof (b0->pre_data));
1495       clib_memcpy_fast (&t1->buffer, b1,
1496                         sizeof (b1[0]) - sizeof (b1->pre_data));
1497
1498       clib_memcpy_fast (t0->buffer.pre_data, b0->data,
1499                         sizeof (t0->buffer.pre_data));
1500       clib_memcpy_fast (t1->buffer.pre_data, b1->data,
1501                         sizeof (t1->buffer.pre_data));
1502     }
1503
1504   while (n_left >= 1)
1505     {
1506       u32 bi0;
1507       vlib_buffer_t *b0;
1508       pg_input_trace_t *t0;
1509
1510       bi0 = b[0];
1511       b += 1;
1512       n_left -= 1;
1513
1514       b0 = vlib_get_buffer (vm, bi0);
1515
1516       vlib_trace_buffer (vm, node, next_index, b0, /* follow_chain */ 1);
1517       t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1518
1519       t0->stream_index = stream_index;
1520       t0->packet_length = vlib_buffer_length_in_chain (vm, b0);
1521       t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1522       clib_memcpy_fast (&t0->buffer, b0,
1523                         sizeof (b0[0]) - sizeof (b0->pre_data));
1524       clib_memcpy_fast (t0->buffer.pre_data, b0->data,
1525                         sizeof (t0->buffer.pre_data));
1526     }
1527 }
1528
1529 static uword
1530 pg_generate_packets (vlib_node_runtime_t * node,
1531                      pg_main_t * pg,
1532                      pg_stream_t * s, uword n_packets_to_generate)
1533 {
1534   vlib_main_t *vm = vlib_get_main ();
1535   u32 *to_next, n_this_frame, n_left, n_trace, n_packets_in_fifo;
1536   uword n_packets_generated;
1537   pg_buffer_index_t *bi, *bi0;
1538   u32 next_index = s->next_index;
1539   vnet_feature_main_t *fm = &feature_main;
1540   vnet_feature_config_main_t *cm;
1541   u8 feature_arc_index = fm->device_input_feature_arc_index;
1542   cm = &fm->feature_config_mains[feature_arc_index];
1543   u32 current_config_index = ~(u32) 0;
1544   int i;
1545
1546   bi0 = s->buffer_indices;
1547
1548   n_packets_in_fifo = pg_stream_fill (pg, s, n_packets_to_generate);
1549   n_packets_to_generate = clib_min (n_packets_in_fifo, n_packets_to_generate);
1550   n_packets_generated = 0;
1551
1552   if (PREDICT_FALSE
1553       (vnet_have_features (feature_arc_index, s->sw_if_index[VLIB_RX])))
1554     {
1555       current_config_index =
1556         vec_elt (cm->config_index_by_sw_if_index, s->sw_if_index[VLIB_RX]);
1557       vnet_get_config_data (&cm->config_main, &current_config_index,
1558                             &next_index, 0);
1559     }
1560
1561   while (n_packets_to_generate > 0)
1562     {
1563       u32 *head, *start, *end;
1564
1565       if (PREDICT_TRUE (next_index == VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT))
1566         {
1567           vlib_next_frame_t *nf;
1568           vlib_frame_t *f;
1569           ethernet_input_frame_t *ef;
1570           pg_interface_t *pi;
1571           vlib_get_new_next_frame (vm, node, next_index, to_next, n_left);
1572           nf = vlib_node_runtime_get_next_frame (vm, node, next_index);
1573           f = vlib_get_frame (vm, nf->frame_index);
1574           f->flags = ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX;
1575
1576           ef = vlib_frame_scalar_args (f);
1577           pi = pool_elt_at_index (pg->interfaces, s->pg_if_index);
1578           ef->sw_if_index = pi->sw_if_index;
1579           ef->hw_if_index = pi->hw_if_index;
1580         }
1581       else
1582         vlib_get_next_frame (vm, node, next_index, to_next, n_left);
1583
1584       n_this_frame = n_packets_to_generate;
1585       if (n_this_frame > n_left)
1586         n_this_frame = n_left;
1587
1588       start = bi0->buffer_fifo;
1589       end = clib_fifo_end (bi0->buffer_fifo);
1590       head = clib_fifo_head (bi0->buffer_fifo);
1591
1592       if (head + n_this_frame <= end)
1593         clib_memcpy_fast (to_next, head, n_this_frame * sizeof (u32));
1594       else
1595         {
1596           u32 n = end - head;
1597           clib_memcpy_fast (to_next + 0, head, n * sizeof (u32));
1598           clib_memcpy_fast (to_next + n, start,
1599                             (n_this_frame - n) * sizeof (u32));
1600         }
1601
1602       if (s->replay_packet_templates == 0)
1603         {
1604           vec_foreach (bi, s->buffer_indices)
1605             clib_fifo_advance_head (bi->buffer_fifo, n_this_frame);
1606         }
1607       else
1608         {
1609           clib_fifo_advance_head (bi0->buffer_fifo, n_this_frame);
1610         }
1611
1612       if (current_config_index != ~(u32) 0)
1613         for (i = 0; i < n_this_frame; i++)
1614           {
1615             vlib_buffer_t *b;
1616             b = vlib_get_buffer (vm, to_next[i]);
1617             b->current_config_index = current_config_index;
1618             vnet_buffer (b)->feature_arc_index = feature_arc_index;
1619           }
1620
1621       n_trace = vlib_get_trace_count (vm, node);
1622       if (n_trace > 0)
1623         {
1624           u32 n = clib_min (n_trace, n_this_frame);
1625           pg_input_trace (pg, node, s, to_next, n);
1626           vlib_set_trace_count (vm, node, n_trace - n);
1627         }
1628       n_packets_to_generate -= n_this_frame;
1629       n_packets_generated += n_this_frame;
1630       n_left -= n_this_frame;
1631       if (CLIB_DEBUG > 0)
1632         {
1633           int i;
1634           vlib_buffer_t *b;
1635
1636           for (i = 0; i < VLIB_FRAME_SIZE - n_left; i++)
1637             {
1638               b = vlib_get_buffer (vm, to_next[i]);
1639               ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0 ||
1640                       b->current_length >= VLIB_BUFFER_MIN_CHAIN_SEG_SIZE);
1641             }
1642         }
1643       vlib_put_next_frame (vm, node, next_index, n_left);
1644     }
1645
1646   return n_packets_generated;
1647 }
1648
1649 static uword
1650 pg_input_stream (vlib_node_runtime_t * node, pg_main_t * pg, pg_stream_t * s)
1651 {
1652   vlib_main_t *vm = vlib_get_main ();
1653   uword n_packets;
1654   f64 time_now, dt;
1655
1656   if (s->n_packets_limit > 0 && s->n_packets_generated >= s->n_packets_limit)
1657     {
1658       pg_stream_enable_disable (pg, s, /* want_enabled */ 0);
1659       return 0;
1660     }
1661
1662   /* Apply rate limit. */
1663   time_now = vlib_time_now (vm);
1664   if (s->time_last_generate == 0)
1665     s->time_last_generate = time_now;
1666
1667   dt = time_now - s->time_last_generate;
1668   s->time_last_generate = time_now;
1669
1670   n_packets = VLIB_FRAME_SIZE;
1671   if (s->rate_packets_per_second > 0)
1672     {
1673       s->packet_accumulator += dt * s->rate_packets_per_second;
1674       n_packets = s->packet_accumulator;
1675
1676       /* Never allow accumulator to grow if we get behind. */
1677       s->packet_accumulator -= n_packets;
1678     }
1679
1680   /* Apply fixed limit. */
1681   if (s->n_packets_limit > 0
1682       && s->n_packets_generated + n_packets > s->n_packets_limit)
1683     n_packets = s->n_packets_limit - s->n_packets_generated;
1684
1685   /* Generate up to one frame's worth of packets. */
1686   if (n_packets > VLIB_FRAME_SIZE)
1687     n_packets = VLIB_FRAME_SIZE;
1688
1689   if (n_packets > 0)
1690     n_packets = pg_generate_packets (node, pg, s, n_packets);
1691
1692   s->n_packets_generated += n_packets;
1693
1694   return n_packets;
1695 }
1696
1697 uword
1698 pg_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1699 {
1700   uword i;
1701   pg_main_t *pg = &pg_main;
1702   uword n_packets = 0;
1703   u32 worker_index = 0;
1704
1705   if (vlib_num_workers ())
1706     worker_index = vlib_get_current_worker_index ();
1707
1708   /* *INDENT-OFF* */
1709   clib_bitmap_foreach (i, pg->enabled_streams[worker_index], ({
1710     pg_stream_t *s = vec_elt_at_index (pg->streams, i);
1711     n_packets += pg_input_stream (node, pg, s);
1712   }));
1713   /* *INDENT-ON* */
1714
1715   return n_packets;
1716 }
1717
1718 /* *INDENT-OFF* */
1719 VLIB_REGISTER_NODE (pg_input_node) = {
1720   .function = pg_input,
1721   .name = "pg-input",
1722   .sibling_of = "device-input",
1723   .type = VLIB_NODE_TYPE_INPUT,
1724
1725   .format_trace = format_pg_input_trace,
1726
1727   /* Input node will be left disabled until a stream is active. */
1728   .state = VLIB_NODE_STATE_DISABLED,
1729 };
1730 /* *INDENT-ON* */
1731
1732 /*
1733  * fd.io coding-style-patch-verification: ON
1734  *
1735  * Local Variables:
1736  * eval: (c-set-style "gnu")
1737  * End:
1738  */