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