Increase window size for latency accuracy
[samplevnf.git] / VNFs / DPPD-PROX / handle_gen.c
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #include <rte_mbuf.h>
17 #include <pcap.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <rte_cycles.h>
21 #include <rte_version.h>
22 #include <rte_byteorder.h>
23 #include <rte_ether.h>
24 #include <rte_hash_crc.h>
25
26 #include "prox_shared.h"
27 #include "random.h"
28 #include "prox_malloc.h"
29 #include "handle_gen.h"
30 #include "handle_lat.h"
31 #include "task_init.h"
32 #include "task_base.h"
33 #include "prox_port_cfg.h"
34 #include "lconf.h"
35 #include "log.h"
36 #include "quit.h"
37 #include "prox_cfg.h"
38 #include "mbuf_utils.h"
39 #include "qinq.h"
40 #include "prox_cksum.h"
41 #include "etypes.h"
42 #include "prox_assert.h"
43 #include "prefetch.h"
44 #include "token_time.h"
45 #include "local_mbuf.h"
46 #include "arp.h"
47 #include "tx_pkt.h"
48 #include "handle_master.h"
49
50 struct pkt_template {
51         uint16_t len;
52         uint16_t l2_len;
53         uint16_t l3_len;
54         uint8_t  *buf;
55 };
56
57 #define MAX_TEMPLATE_INDEX      65536
58 #define TEMPLATE_INDEX_MASK     (MAX_TEMPLATE_INDEX - 1)
59
60 #define IP4(x) x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, x >> 24
61
62 static void pkt_template_init_mbuf(struct pkt_template *pkt_template, struct rte_mbuf *mbuf, uint8_t *pkt)
63 {
64         const uint32_t pkt_size = pkt_template->len;
65
66         rte_pktmbuf_pkt_len(mbuf) = pkt_size;
67         rte_pktmbuf_data_len(mbuf) = pkt_size;
68         init_mbuf_seg(mbuf);
69         rte_memcpy(pkt, pkt_template->buf, pkt_template->len);
70 }
71
72 struct task_gen_pcap {
73         struct task_base base;
74         uint64_t hz;
75         struct local_mbuf local_mbuf;
76         uint32_t pkt_idx;
77         struct pkt_template *proto;
78         uint32_t loop;
79         uint32_t n_pkts;
80         uint64_t last_tsc;
81         uint64_t *proto_tsc;
82 };
83
84 struct task_gen {
85         struct task_base base;
86         uint64_t hz;
87         struct token_time token_time;
88         struct local_mbuf local_mbuf;
89         struct pkt_template *pkt_template; /* packet templates used at runtime */
90         uint64_t write_duration_estimate; /* how long it took previously to write the time stamps in the packets */
91         uint64_t earliest_tsc_next_pkt;
92         uint64_t new_rate_bps;
93         uint64_t pkt_queue_index;
94         uint32_t n_pkts; /* number of packets in pcap */
95         uint32_t pkt_idx; /* current packet from pcap */
96         uint32_t pkt_count; /* how many pakets to generate */
97         uint32_t max_frame_size;
98         uint32_t runtime_flags;
99         uint16_t lat_pos;
100         uint16_t packet_id_pos;
101         uint16_t accur_pos;
102         uint16_t sig_pos;
103         uint32_t sig;
104         uint8_t generator_id;
105         uint8_t n_rands; /* number of randoms */
106         uint8_t min_bulk_size;
107         uint8_t max_bulk_size;
108         uint8_t lat_enabled;
109         uint8_t runtime_checksum_needed;
110         struct {
111                 struct random state;
112                 uint32_t rand_mask; /* since the random vals are uniform, masks don't introduce bias  */
113                 uint32_t fixed_bits; /* length of each random (max len = 4) */
114                 uint16_t rand_offset; /* each random has an offset*/
115                 uint8_t rand_len; /* # bytes to take from random (no bias introduced) */
116         } rand[64];
117         uint64_t accur[ACCURACY_WINDOW];
118         uint64_t pkt_tsc_offset[64];
119         struct pkt_template *pkt_template_orig; /* packet templates (from inline or from pcap) */
120         struct ether_addr  src_mac;
121         uint8_t flags;
122         uint8_t cksum_offload;
123         struct prox_port_cfg *port;
124         uint64_t *bytes_to_tsc;
125 } __rte_cache_aligned;
126
127 static inline uint8_t ipv4_get_hdr_len(struct ipv4_hdr *ip)
128 {
129         /* Optimize for common case of IPv4 header without options. */
130         if (ip->version_ihl == 0x45)
131                 return sizeof(struct ipv4_hdr);
132         if (unlikely(ip->version_ihl >> 4 != 4)) {
133                 plog_warn("IPv4 ether_type but IP version = %d != 4", ip->version_ihl >> 4);
134                 return 0;
135         }
136         return (ip->version_ihl & 0xF) * 4;
137 }
138
139 static void parse_l2_l3_len(uint8_t *pkt, uint16_t *l2_len, uint16_t *l3_len, uint16_t len)
140 {
141         *l2_len = sizeof(struct ether_hdr);
142         *l3_len = 0;
143         struct vlan_hdr *vlan_hdr;
144         struct ether_hdr *eth_hdr = (struct ether_hdr*)pkt;
145         struct ipv4_hdr *ip;
146         uint16_t ether_type = eth_hdr->ether_type;
147
148         // Unstack VLAN tags
149         while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (*l2_len + sizeof(struct vlan_hdr) < len)) {
150                 vlan_hdr = (struct vlan_hdr *)(pkt + *l2_len);
151                 *l2_len +=4;
152                 ether_type = vlan_hdr->eth_proto;
153         }
154
155         // No L3 cksum offload for IPv6, but TODO L4 offload
156         // ETYPE_EoGRE CRC not implemented yet
157
158         switch (ether_type) {
159         case ETYPE_MPLSU:
160         case ETYPE_MPLSM:
161                 *l2_len +=4;
162                 break;
163         case ETYPE_IPv4:
164                 break;
165         case ETYPE_EoGRE:
166         case ETYPE_ARP:
167         case ETYPE_IPv6:
168                 *l2_len = 0;
169                 break;
170         default:
171                 *l2_len = 0;
172                 plog_warn("Unsupported packet type %x - CRC might be wrong\n", ether_type);
173                 break;
174         }
175
176         if (*l2_len) {
177                 struct ipv4_hdr *ip = (struct ipv4_hdr *)(pkt + *l2_len);
178                 *l3_len = ipv4_get_hdr_len(ip);
179         }
180 }
181
182 static void checksum_packet(uint8_t *hdr, struct rte_mbuf *mbuf, struct pkt_template *pkt_template, int cksum_offload)
183 {
184         uint16_t l2_len = pkt_template->l2_len;
185         uint16_t l3_len = pkt_template->l3_len;
186
187         if (l2_len) {
188                 struct ipv4_hdr *ip = (struct ipv4_hdr*)(hdr + l2_len);
189                 prox_ip_udp_cksum(mbuf, ip, l2_len, l3_len, cksum_offload);
190         }
191 }
192
193 static void task_gen_reset_token_time(struct task_gen *task)
194 {
195         token_time_set_bpp(&task->token_time, task->new_rate_bps);
196         token_time_reset(&task->token_time, rte_rdtsc(), 0);
197 }
198
199 static void task_gen_take_count(struct task_gen *task, uint32_t send_bulk)
200 {
201         if (task->pkt_count == (uint32_t)-1)
202                 return ;
203         else {
204                 if (task->pkt_count >= send_bulk)
205                         task->pkt_count -= send_bulk;
206                 else
207                         task->pkt_count = 0;
208         }
209 }
210
211 static int handle_gen_pcap_bulk(struct task_base *tbase, struct rte_mbuf **mbuf, uint16_t n_pkts)
212 {
213         struct task_gen_pcap *task = (struct task_gen_pcap *)tbase;
214         uint64_t now = rte_rdtsc();
215         uint64_t send_bulk = 0;
216         uint32_t pkt_idx_tmp = task->pkt_idx;
217
218         if (pkt_idx_tmp == task->n_pkts) {
219                 PROX_ASSERT(task->loop);
220                 return 0;
221         }
222
223         for (uint16_t j = 0; j < 64; ++j) {
224                 uint64_t tsc = task->proto_tsc[pkt_idx_tmp];
225                 if (task->last_tsc + tsc <= now) {
226                         task->last_tsc += tsc;
227                         send_bulk++;
228                         pkt_idx_tmp++;
229                         if (pkt_idx_tmp == task->n_pkts) {
230                                 if (task->loop)
231                                         pkt_idx_tmp = 0;
232                                 else
233                                         break;
234                         }
235                 }
236                 else
237                         break;
238         }
239
240         struct rte_mbuf **new_pkts = local_mbuf_refill_and_take(&task->local_mbuf, send_bulk);
241         if (new_pkts == NULL)
242                 return 0;
243
244         for (uint16_t j = 0; j < send_bulk; ++j) {
245                 struct rte_mbuf *next_pkt = new_pkts[j];
246                 struct pkt_template *pkt_template = &task->proto[task->pkt_idx];
247                 uint8_t *hdr = rte_pktmbuf_mtod(next_pkt, uint8_t *);
248
249                 pkt_template_init_mbuf(pkt_template, next_pkt, hdr);
250
251                 task->pkt_idx++;
252                 if (task->pkt_idx == task->n_pkts) {
253                         if (task->loop)
254                                 task->pkt_idx = 0;
255                         else
256                                 break;
257                 }
258         }
259
260         return task->base.tx_pkt(&task->base, new_pkts, send_bulk, NULL);
261 }
262
263 static inline uint64_t bytes_to_tsc(struct task_gen *task, uint32_t bytes)
264 {
265         return task->bytes_to_tsc[bytes];
266 }
267
268 static uint32_t task_gen_next_pkt_idx(const struct task_gen *task, uint32_t pkt_idx)
269 {
270         return pkt_idx + 1 == task->n_pkts? 0 : pkt_idx + 1;
271 }
272
273 static uint32_t task_gen_offset_pkt_idx(const struct task_gen *task, uint32_t offset)
274 {
275         return (task->pkt_idx + offset) % task->n_pkts;
276 }
277
278 static uint32_t task_gen_calc_send_bulk(const struct task_gen *task, uint32_t *total_bytes)
279 {
280         /* The biggest bulk we allow to send is task->max_bulk_size
281            packets. The max bulk size can also be limited by the
282            pkt_count field.  At the same time, we are rate limiting
283            based on the specified speed (in bytes per second) so token
284            bucket based rate limiting must also be applied. The
285            minimum bulk size is also constrained. If the calculated
286            bulk size is less then the minimum, then don't send
287            anything. */
288
289         const uint32_t min_bulk = task->min_bulk_size;
290         uint32_t max_bulk = task->max_bulk_size;
291
292         if (task->pkt_count != (uint32_t)-1 && task->pkt_count < max_bulk) {
293                 max_bulk = task->pkt_count;
294         }
295
296         uint32_t send_bulk = 0;
297         uint32_t pkt_idx_tmp = task->pkt_idx;
298         uint32_t would_send_bytes = 0;
299         uint32_t pkt_size;
300
301         /*
302          * TODO - this must be improved to take into account the fact that, after applying randoms
303          * The packet can be replaced by an ARP
304          */
305         for (uint16_t j = 0; j < max_bulk; ++j) {
306                 struct pkt_template *pktpl = &task->pkt_template[pkt_idx_tmp];
307                 pkt_size = pktpl->len;
308                 uint32_t pkt_len = pkt_len_to_wire_size(pkt_size);
309                 if (pkt_len + would_send_bytes > task->token_time.bytes_now)
310                         break;
311
312                 pkt_idx_tmp = task_gen_next_pkt_idx(task, pkt_idx_tmp);
313
314                 send_bulk++;
315                 would_send_bytes += pkt_len;
316         }
317
318         if (send_bulk < min_bulk)
319                 return 0;
320         *total_bytes = would_send_bytes;
321         return send_bulk;
322 }
323
324 static void task_gen_apply_random_fields(struct task_gen *task, uint8_t *hdr)
325 {
326         uint32_t ret, ret_tmp;
327
328         for (uint16_t i = 0; i < task->n_rands; ++i) {
329                 ret = random_next(&task->rand[i].state);
330                 ret_tmp = (ret & task->rand[i].rand_mask) | task->rand[i].fixed_bits;
331
332                 ret_tmp = rte_bswap32(ret_tmp);
333                 /* At this point, the lower order bytes (BE) contain
334                    the generated value. The address where the values
335                    of interest starts is at ret_tmp + 4 - rand_len. */
336                 uint8_t *pret_tmp = (uint8_t*)&ret_tmp;
337                 rte_memcpy(hdr + task->rand[i].rand_offset, pret_tmp + 4 - task->rand[i].rand_len, task->rand[i].rand_len);
338         }
339 }
340
341 static void task_gen_apply_all_random_fields(struct task_gen *task, uint8_t **pkt_hdr, uint32_t count)
342 {
343         if (!task->n_rands)
344                 return;
345
346         for (uint16_t i = 0; i < count; ++i)
347                 task_gen_apply_random_fields(task, pkt_hdr[i]);
348 }
349
350 static void task_gen_apply_accur_pos(struct task_gen *task, uint8_t *pkt_hdr, uint32_t accuracy)
351 {
352         *(uint32_t *)(pkt_hdr + task->accur_pos) = accuracy;
353 }
354
355 static void task_gen_apply_sig(struct task_gen *task, struct pkt_template *dst)
356 {
357         if (task->sig_pos)
358                 *(uint32_t *)(dst->buf + task->sig_pos) = task->sig;
359 }
360
361 static void task_gen_apply_all_accur_pos(struct task_gen *task, struct rte_mbuf **mbufs, uint8_t **pkt_hdr, uint32_t count)
362 {
363         if (!task->accur_pos)
364                 return;
365
366         /* The accuracy of task->pkt_queue_index - ACCURACY_WINDOW is stored in
367            packet task->pkt_queue_index. The ID modulo ACCURACY_WINDOW is the
368            same. */
369         for (uint16_t j = 0; j < count; ++j) {
370                 uint32_t accuracy = task->accur[(task->pkt_queue_index + j) & (ACCURACY_WINDOW - 1)];
371                 task_gen_apply_accur_pos(task, pkt_hdr[j], accuracy);
372         }
373 }
374
375 static void task_gen_apply_unique_id(struct task_gen *task, uint8_t *pkt_hdr, const struct unique_id *id)
376 {
377         struct unique_id *dst = (struct unique_id *)(pkt_hdr + task->packet_id_pos);
378
379         *dst = *id;
380 }
381
382 static void task_gen_apply_all_unique_id(struct task_gen *task, struct rte_mbuf **mbufs, uint8_t **pkt_hdr, uint32_t count)
383 {
384         if (!task->packet_id_pos)
385                 return;
386
387         for (uint16_t i = 0; i < count; ++i) {
388                 struct unique_id id;
389                 unique_id_init(&id, task->generator_id, task->pkt_queue_index++);
390                 task_gen_apply_unique_id(task, pkt_hdr[i], &id);
391         }
392 }
393
394 static void task_gen_checksum_packets(struct task_gen *task, struct rte_mbuf **mbufs, uint8_t **pkt_hdr, uint32_t count)
395 {
396         if (!(task->runtime_flags & TASK_TX_CRC))
397                 return;
398
399         if (!task->runtime_checksum_needed)
400                 return;
401
402         uint32_t pkt_idx = task_gen_offset_pkt_idx(task, - count);
403         for (uint16_t i = 0; i < count; ++i) {
404                 struct pkt_template *pkt_template = &task->pkt_template[pkt_idx];
405                 checksum_packet(pkt_hdr[i], mbufs[i], pkt_template, task->cksum_offload);
406                 pkt_idx = task_gen_next_pkt_idx(task, pkt_idx);
407         }
408 }
409
410 static void task_gen_consume_tokens(struct task_gen *task, uint32_t tokens, uint32_t send_count)
411 {
412         /* If max burst has been sent, we can't keep up so just assume
413            that we can (leaving a "gap" in the packet stream on the
414            wire) */
415         task->token_time.bytes_now -= tokens;
416         if (send_count == task->max_bulk_size && task->token_time.bytes_now > tokens) {
417                 task->token_time.bytes_now = tokens;
418         }
419 }
420
421 static uint64_t task_gen_calc_bulk_duration(struct task_gen *task, uint32_t count)
422 {
423         uint32_t pkt_idx = task_gen_offset_pkt_idx(task, - 1);
424         struct pkt_template *last_pkt_template = &task->pkt_template[pkt_idx];
425         uint32_t last_pkt_len = pkt_len_to_wire_size(last_pkt_template->len);
426 #ifdef NO_EXTRAPOLATION
427         uint64_t bulk_duration = task->pkt_tsc_offset[count - 1];
428 #else
429         uint64_t last_pkt_duration = bytes_to_tsc(task, last_pkt_len);
430         uint64_t bulk_duration = task->pkt_tsc_offset[count - 1] + last_pkt_duration;
431 #endif
432
433         return bulk_duration;
434 }
435
436 static uint64_t task_gen_write_latency(struct task_gen *task, uint8_t **pkt_hdr, uint32_t count)
437 {
438         if (!task->lat_enabled)
439                 return 0;
440
441         uint64_t tx_tsc, delta_t;
442         uint64_t tsc_before_tx = 0;
443
444         /* Just before sending the packets, apply the time stamp
445            relative to when the first packet will be sent. The first
446            packet will be sent now. The time is read for each packet
447            to reduce the error towards the actual time the packet will
448            be sent. */
449         uint64_t write_tsc_after, write_tsc_before;
450
451         write_tsc_before = rte_rdtsc();
452
453         /* The time it took previously to write the time stamps in the
454            packets is used as an estimate for how long it will take to
455            write the time stamps now.  The estimated time at which the
456            packets will actually be sent will be at tx_tsc. */
457         tx_tsc = write_tsc_before + task->write_duration_estimate;
458
459         /* The offset delta_t tracks the difference between the actual
460            time and the time written in the packets. Adding the offset
461            to the actual time insures that the time written in the
462            packets is monotonically increasing. At the same time,
463            simply sleeping until delta_t is zero would leave a period
464            of silence on the line. The error has been introduced
465            earlier, but the packets have already been sent. */
466
467         /* This happens typically if previous bulk was delayed
468            by an interrupt e.g.  (with Time in nsec)
469            Time x: sleep 4 microsec
470            Time x+4000: send 64 packets (64 packets as 4000 nsec, w/ 10Gbps 64 bytes)
471            Time x+5000: send 16 packets (16 packets as 1000 nsec)
472            When we send the 16 packets, the 64 ealier packets are not yet
473            fully sent */
474         if (tx_tsc < task->earliest_tsc_next_pkt)
475                 delta_t = task->earliest_tsc_next_pkt - tx_tsc;
476         else
477                 delta_t = 0;
478
479         for (uint16_t i = 0; i < count; ++i) {
480                 uint32_t *pos = (uint32_t *)(pkt_hdr[i] + task->lat_pos);
481                 const uint64_t pkt_tsc = tx_tsc + delta_t + task->pkt_tsc_offset[i];
482                 *pos = pkt_tsc >> LATENCY_ACCURACY;
483         }
484
485         uint64_t bulk_duration = task_gen_calc_bulk_duration(task, count);
486         task->earliest_tsc_next_pkt = tx_tsc + delta_t + bulk_duration;
487         write_tsc_after = rte_rdtsc();
488         task->write_duration_estimate = write_tsc_after - write_tsc_before;
489
490         /* Make sure that the time stamps that were written
491            are valid. The offset must be taken into account */
492         do {
493                 tsc_before_tx = rte_rdtsc();
494         } while (tsc_before_tx < tx_tsc);
495
496         return tsc_before_tx;
497 }
498
499 static void task_gen_store_accuracy(struct task_gen *task, uint32_t count, uint64_t tsc_before_tx)
500 {
501         if (!task->accur_pos)
502                 return;
503
504         uint64_t accur = rte_rdtsc() - tsc_before_tx;
505         uint64_t first_accuracy_idx = task->pkt_queue_index - count;
506
507         for (uint32_t i = 0; i < count; ++i) {
508                 uint32_t accuracy_idx = (first_accuracy_idx + i) & (ACCURACY_WINDOW - 1);
509
510                 task->accur[accuracy_idx] = accur;
511         }
512 }
513
514 static void task_gen_load_and_prefetch(struct rte_mbuf **mbufs, uint8_t **pkt_hdr, uint32_t count)
515 {
516         for (uint16_t i = 0; i < count; ++i)
517                 rte_prefetch0(mbufs[i]);
518         for (uint16_t i = 0; i < count; ++i)
519                 pkt_hdr[i] = rte_pktmbuf_mtod(mbufs[i], uint8_t *);
520         for (uint16_t i = 0; i < count; ++i)
521                 rte_prefetch0(pkt_hdr[i]);
522 }
523
524 static void task_gen_build_packets(struct task_gen *task, struct rte_mbuf **mbufs, uint8_t **pkt_hdr, uint32_t count)
525 {
526         uint64_t will_send_bytes = 0;
527
528         for (uint16_t i = 0; i < count; ++i) {
529                 struct pkt_template *pktpl = &task->pkt_template[task->pkt_idx];
530                 struct pkt_template *pkt_template = &task->pkt_template[task->pkt_idx];
531                 pkt_template_init_mbuf(pkt_template, mbufs[i], pkt_hdr[i]);
532                 mbufs[i]->udata64 = task->pkt_idx & TEMPLATE_INDEX_MASK;
533                 struct ether_hdr *hdr = (struct ether_hdr *)pkt_hdr[i];
534                 if (task->lat_enabled) {
535 #ifdef NO_EXTRAPOLATION
536                         task->pkt_tsc_offset[i] = 0;
537 #else
538                         task->pkt_tsc_offset[i] = bytes_to_tsc(task, will_send_bytes);
539 #endif
540                         will_send_bytes += pkt_len_to_wire_size(pkt_template->len);
541                 }
542                 task->pkt_idx = task_gen_next_pkt_idx(task, task->pkt_idx);
543         }
544 }
545
546 static void task_gen_update_config(struct task_gen *task)
547 {
548         if (task->token_time.cfg.bpp != task->new_rate_bps)
549                 task_gen_reset_token_time(task);
550 }
551
552 static inline void build_value(struct task_gen *task, uint32_t mask, int bit_pos, uint32_t val, uint32_t fixed_bits)
553 {
554         struct task_base *tbase = (struct task_base *)task;
555         if (bit_pos < 32) {
556                 build_value(task, mask >> 1, bit_pos + 1, val, fixed_bits);
557                 if (mask & 1) {
558                         build_value(task, mask >> 1, bit_pos + 1, val | (1 << bit_pos), fixed_bits);
559                 }
560         } else {
561                 register_ip_to_ctrl_plane(tbase->l3.tmaster, rte_cpu_to_be_32(val | fixed_bits), tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
562         }
563 }
564 static inline void register_all_ip_to_ctrl_plane(struct task_gen *task)
565 {
566         struct task_base *tbase = (struct task_base *)task;
567         int i, len, fixed;
568         unsigned int offset;
569         uint32_t mask;
570
571         for (uint32_t i = 0; i < task->n_pkts; ++i) {
572                 struct pkt_template *pktpl = &task->pkt_template[i];
573                 unsigned int ip_src_pos = 0;
574                 int maybe_ipv4 = 0;
575                 unsigned int l2_len = sizeof(struct ether_hdr);
576
577                 uint8_t *pkt = pktpl->buf;
578                 struct ether_hdr *eth_hdr = (struct ether_hdr*)pkt;
579                 uint16_t ether_type = eth_hdr->ether_type;
580                 struct vlan_hdr *vlan_hdr;
581
582                 // Unstack VLAN tags
583                 while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(struct vlan_hdr) < pktpl->len)) {
584                         vlan_hdr = (struct vlan_hdr *)(pkt + l2_len);
585                         l2_len +=4;
586                         ether_type = vlan_hdr->eth_proto;
587                 }
588                 if ((ether_type == ETYPE_MPLSU) || (ether_type == ETYPE_MPLSM)) {
589                         l2_len +=4;
590                         maybe_ipv4 = 1;
591                 }
592                 if ((ether_type != ETYPE_IPv4) && !maybe_ipv4)
593                         continue;
594
595                 struct ipv4_hdr *ip = (struct ipv4_hdr *)(pkt + l2_len);
596                 PROX_PANIC(ip->version_ihl >> 4 != 4, "IPv4 ether_type but IP version = %d != 4", ip->version_ihl >> 4);
597
598                 // Even if IPv4 header contains options, options are after ip src and dst
599                 ip_src_pos = l2_len + sizeof(struct ipv4_hdr) - 2 * sizeof(uint32_t);
600                 uint32_t *ip_src = ((uint32_t *)(pktpl->buf + ip_src_pos));
601                 plog_info("\tip_src_pos = %d, ip_src = %x\n", ip_src_pos, *ip_src);
602                 register_ip_to_ctrl_plane(tbase->l3.tmaster, *ip_src, tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
603
604                 for (int j = 0; j < task->n_rands; j++) {
605                         offset = task->rand[j].rand_offset;
606                         len = task->rand[j].rand_len;
607                         mask = task->rand[j].rand_mask;
608                         fixed = task->rand[j].fixed_bits;
609                         plog_info("offset = %d, len = %d, mask = %x, fixed = %x\n", offset, len, mask, fixed);
610                         if ((offset < ip_src_pos + 4) && (offset + len >= ip_src_pos)) {
611                                 if (offset >= ip_src_pos) {
612                                         int32_t ip_src_mask = (1 << (4 + ip_src_pos - offset) * 8) - 1;
613                                         mask = mask & ip_src_mask;
614                                         fixed = (fixed & ip_src_mask) | (rte_be_to_cpu_32(*ip_src) & ~ip_src_mask);
615                                         build_value(task, mask, 0, 0, fixed);
616                                 } else {
617                                         int32_t bits = ((ip_src_pos + 4 - offset - len) * 8);
618                                         mask = mask << bits;
619                                         fixed = (fixed << bits) | (rte_be_to_cpu_32(*ip_src) & ((1 << bits) - 1));
620                                         build_value(task, mask, 0, 0, fixed);
621                                 }
622                         }
623                 }
624         }
625 }
626
627 static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
628 {
629         struct task_gen *task = (struct task_gen *)tbase;
630         uint8_t out[MAX_PKT_BURST] = {0};
631         int ret;
632
633         int i, j;
634
635         task_gen_update_config(task);
636
637         if (task->pkt_count == 0) {
638                 task_gen_reset_token_time(task);
639                 return 0;
640         }
641         if (!task->token_time.cfg.bpp)
642                 return 0;
643
644         token_time_update(&task->token_time, rte_rdtsc());
645
646         uint32_t would_send_bytes;
647         uint32_t send_bulk = task_gen_calc_send_bulk(task, &would_send_bytes);
648
649         if (send_bulk == 0)
650                 return 0;
651         task_gen_take_count(task, send_bulk);
652         task_gen_consume_tokens(task, would_send_bytes, send_bulk);
653
654         struct rte_mbuf **new_pkts = local_mbuf_refill_and_take(&task->local_mbuf, send_bulk);
655         if (new_pkts == NULL)
656                 return 0;
657         uint8_t *pkt_hdr[MAX_RING_BURST];
658
659         task_gen_load_and_prefetch(new_pkts, pkt_hdr, send_bulk);
660         task_gen_build_packets(task, new_pkts, pkt_hdr, send_bulk);
661         task_gen_apply_all_random_fields(task, pkt_hdr, send_bulk);
662         task_gen_apply_all_accur_pos(task, new_pkts, pkt_hdr, send_bulk);
663         task_gen_apply_all_unique_id(task, new_pkts, pkt_hdr, send_bulk);
664
665         uint64_t tsc_before_tx;
666
667         tsc_before_tx = task_gen_write_latency(task, pkt_hdr, send_bulk);
668         task_gen_checksum_packets(task, new_pkts, pkt_hdr, send_bulk);
669         ret = task->base.tx_pkt(&task->base, new_pkts, send_bulk, out);
670         task_gen_store_accuracy(task, send_bulk, tsc_before_tx);
671
672         // If we failed to send some packets, we need to do some clean-up:
673
674         if (unlikely(ret)) {
675                 // We need re-use the packets indexes not being sent
676                 // Hence non-sent packets will not be considered as lost by the receiver when it looks at
677                 // packet ids. This should also increase the percentage of packets used for latency measurements
678                 task->pkt_queue_index -= ret;
679
680                 // In case of failures, the estimate about when we can send next packet (earliest_tsc_next_pkt) is wrong
681                 // This would result in under-estimated latency (up to 0 or negative)
682                 uint64_t bulk_duration = task_gen_calc_bulk_duration(task, ret);
683                 task->earliest_tsc_next_pkt -= bulk_duration;
684         }
685         return ret;
686 }
687
688 static void init_task_gen_seeds(struct task_gen *task)
689 {
690         for (size_t i = 0; i < sizeof(task->rand)/sizeof(task->rand[0]); ++i)
691                 random_init_seed(&task->rand[i].state);
692 }
693
694 static uint32_t pcap_count_pkts(pcap_t *handle, uint32_t *max_frame_size)
695 {
696         struct pcap_pkthdr header;
697         const uint8_t *buf;
698         uint32_t ret = 0;
699         *max_frame_size = 0;
700         long pkt1_fpos = ftell(pcap_file(handle));
701
702         while ((buf = pcap_next(handle, &header))) {
703                 if (header.len > *max_frame_size)
704                         *max_frame_size = header.len;
705                 ret++;
706         }
707         int ret2 = fseek(pcap_file(handle), pkt1_fpos, SEEK_SET);
708         PROX_PANIC(ret2 != 0, "Failed to reset reading pcap file\n");
709         return ret;
710 }
711
712 static uint64_t avg_time_stamp(uint64_t *time_stamp, uint32_t n)
713 {
714         uint64_t tot_inter_pkt = 0;
715
716         for (uint32_t i = 0; i < n; ++i)
717                 tot_inter_pkt += time_stamp[i];
718         return (tot_inter_pkt + n / 2)/n;
719 }
720
721 static int pcap_read_pkts(pcap_t *handle, const char *file_name, uint32_t n_pkts, struct pkt_template *proto, uint64_t *time_stamp)
722 {
723         struct pcap_pkthdr header;
724         const uint8_t *buf;
725         size_t len;
726
727         for (uint32_t i = 0; i < n_pkts; ++i) {
728                 buf = pcap_next(handle, &header);
729
730                 PROX_PANIC(buf == NULL, "Failed to read packet %d from pcap %s\n", i, file_name);
731                 proto[i].len = header.len;
732                 len = RTE_MIN(header.len, sizeof(proto[i].buf));
733                 if (header.len > len)
734                         plogx_warn("Packet truncated from %u to %zu bytes\n", header.len, len);
735
736                 if (time_stamp) {
737                         static struct timeval beg;
738                         struct timeval tv;
739
740                         if (i == 0)
741                                 beg = header.ts;
742
743                         tv = tv_diff(&beg, &header.ts);
744                         tv_to_tsc(&tv, time_stamp + i);
745                 }
746                 rte_memcpy(proto[i].buf, buf, len);
747         }
748
749         if (time_stamp && n_pkts) {
750                 for (uint32_t i = n_pkts - 1; i > 0; --i)
751                         time_stamp[i] -= time_stamp[i - 1];
752                 /* Since the handle function will loop the packets,
753                    there is one time-stamp that is not provided by the
754                    pcap file. This is the time between the last and
755                    the first packet. This implementation takes the
756                    average of the inter-packet times here. */
757                 if (n_pkts > 1)
758                         time_stamp[0] = avg_time_stamp(time_stamp + 1, n_pkts - 1);
759         }
760
761         return 0;
762 }
763
764 static int check_pkt_size(struct task_gen *task, uint32_t pkt_size, int do_panic)
765 {
766         const uint16_t min_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr);
767         const uint16_t max_len = task->max_frame_size;
768
769         if (do_panic) {
770                 PROX_PANIC(pkt_size == 0, "Invalid packet size length (no packet defined?)\n");
771                 PROX_PANIC(pkt_size > max_len, "pkt_size out of range (must be <= %u)\n", max_len);
772                 PROX_PANIC(pkt_size < min_len, "pkt_size out of range (must be >= %u)\n", min_len);
773                 return 0;
774         } else {
775                 if (pkt_size == 0) {
776                         plog_err("Invalid packet size length (no packet defined?)\n");
777                         return -1;
778                 }
779                 if (pkt_size > max_len) {
780                         plog_err("pkt_size out of range (must be <= %u)\n", max_len);
781                         return -1;
782                 }
783                 if (pkt_size < min_len) {
784                         plog_err("pkt_size out of range (must be >= %u)\n", min_len);
785                         return -1;
786                 }
787                 return 0;
788         }
789 }
790
791 static int check_all_pkt_size(struct task_gen *task, int do_panic)
792 {
793         int rc;
794         for (uint32_t i = 0; i < task->n_pkts;++i) {
795                 if ((rc = check_pkt_size(task, task->pkt_template[i].len, do_panic)) != 0)
796                         return rc;
797         }
798         return 0;
799 }
800
801 static int check_fields_in_bounds(struct task_gen *task, uint32_t pkt_size, int do_panic)
802 {
803         if (task->lat_enabled) {
804                 uint32_t pos_beg = task->lat_pos;
805                 uint32_t pos_end = task->lat_pos + 3U;
806
807                 if (do_panic)
808                         PROX_PANIC(pkt_size <= pos_end, "Writing latency at %u-%u, but packet size is %u bytes\n",
809                            pos_beg, pos_end, pkt_size);
810                 else if (pkt_size <= pos_end) {
811                         plog_err("Writing latency at %u-%u, but packet size is %u bytes\n", pos_beg, pos_end, pkt_size);
812                         return -1;
813                 }
814         }
815         if (task->packet_id_pos) {
816                 uint32_t pos_beg = task->packet_id_pos;
817                 uint32_t pos_end = task->packet_id_pos + 4U;
818
819                 if (do_panic)
820                         PROX_PANIC(pkt_size <= pos_end, "Writing packet at %u-%u, but packet size is %u bytes\n",
821                            pos_beg, pos_end, pkt_size);
822                 else if (pkt_size <= pos_end) {
823                         plog_err("Writing packet at %u-%u, but packet size is %u bytes\n", pos_beg, pos_end, pkt_size);
824                         return -1;
825                 }
826         }
827         if (task->accur_pos) {
828                 uint32_t pos_beg = task->accur_pos;
829                 uint32_t pos_end = task->accur_pos + 3U;
830
831                 if (do_panic)
832                         PROX_PANIC(pkt_size <= pos_end, "Writing accuracy at %u%-u, but packet size is %u bytes\n",
833                            pos_beg, pos_end, pkt_size);
834                 else if (pkt_size <= pos_end) {
835                         plog_err("Writing accuracy at %u%-u, but packet size is %u bytes\n", pos_beg, pos_end, pkt_size);
836                         return -1;
837                 }
838         }
839         return 0;
840 }
841
842 static void task_gen_pkt_template_recalc_metadata(struct task_gen *task)
843 {
844         struct pkt_template *template;
845
846         for (size_t i = 0; i < task->n_pkts; ++i) {
847                 template = &task->pkt_template[i];
848                 parse_l2_l3_len(template->buf, &template->l2_len, &template->l3_len, template->len);
849         }
850 }
851
852 static void task_gen_pkt_template_recalc_checksum(struct task_gen *task)
853 {
854         struct pkt_template *template;
855         struct ipv4_hdr *ip;
856
857         task->runtime_checksum_needed = 0;
858         for (size_t i = 0; i < task->n_pkts; ++i) {
859                 template = &task->pkt_template[i];
860                 if (template->l2_len == 0)
861                         continue;
862                 ip = (struct ipv4_hdr *)(template->buf + template->l2_len);
863
864                 ip->hdr_checksum = 0;
865                 prox_ip_cksum_sw(ip);
866                 uint32_t l4_len = rte_bswap16(ip->total_length) - template->l3_len;
867
868                 if (ip->next_proto_id == IPPROTO_UDP) {
869                         struct udp_hdr *udp = (struct udp_hdr *)(((uint8_t *)ip) + template->l3_len);
870                         prox_udp_cksum_sw(udp, l4_len, ip->src_addr, ip->dst_addr);
871                 } else if (ip->next_proto_id == IPPROTO_TCP) {
872                         struct tcp_hdr *tcp = (struct tcp_hdr *)(((uint8_t *)ip) + template->l3_len);
873                         prox_tcp_cksum_sw(tcp, l4_len, ip->src_addr, ip->dst_addr);
874                 }
875
876                 /* The current implementation avoids checksum
877                    calculation by determining that at packet
878                    construction time, no fields are applied that would
879                    require a recalculation of the checksum. */
880                 if (task->lat_enabled && task->lat_pos > template->l2_len)
881                         task->runtime_checksum_needed = 1;
882                 if (task->accur_pos > template->l2_len)
883                         task->runtime_checksum_needed = 1;
884                 if (task->packet_id_pos > template->l2_len)
885                         task->runtime_checksum_needed = 1;
886         }
887 }
888
889 static void task_gen_pkt_template_recalc_all(struct task_gen *task)
890 {
891         task_gen_pkt_template_recalc_metadata(task);
892         task_gen_pkt_template_recalc_checksum(task);
893 }
894
895 static void task_gen_reset_pkt_templates_len(struct task_gen *task)
896 {
897         struct pkt_template *src, *dst;
898
899         for (size_t i = 0; i < task->n_pkts; ++i) {
900                 src = &task->pkt_template_orig[i];
901                 dst = &task->pkt_template[i];
902                 dst->len = src->len;
903         }
904 }
905
906 static void task_gen_reset_pkt_templates_content(struct task_gen *task)
907 {
908         struct pkt_template *src, *dst;
909
910         for (size_t i = 0; i < task->n_pkts; ++i) {
911                 src = &task->pkt_template_orig[i];
912                 dst = &task->pkt_template[i];
913                 memcpy(dst->buf, src->buf, dst->len);
914                 task_gen_apply_sig(task, dst);
915         }
916 }
917
918 static void task_gen_reset_pkt_templates(struct task_gen *task)
919 {
920         task_gen_reset_pkt_templates_len(task);
921         task_gen_reset_pkt_templates_content(task);
922         task_gen_pkt_template_recalc_all(task);
923 }
924
925 static void task_init_gen_load_pkt_inline(struct task_gen *task, struct task_args *targ)
926 {
927         const int socket_id = rte_lcore_to_socket_id(targ->lconf->id);
928
929         task->n_pkts = 1;
930
931         size_t mem_size = task->n_pkts * sizeof(*task->pkt_template);
932         task->pkt_template = prox_zmalloc(mem_size, socket_id);
933         task->pkt_template_orig = prox_zmalloc(mem_size, socket_id);
934
935         PROX_PANIC(task->pkt_template == NULL ||
936                    task->pkt_template_orig == NULL,
937                    "Failed to allocate %lu bytes (in huge pages) for packet template\n", mem_size);
938
939         task->pkt_template->buf = prox_zmalloc(task->max_frame_size, socket_id);
940         task->pkt_template_orig->buf = prox_zmalloc(task->max_frame_size, socket_id);
941         PROX_PANIC(task->pkt_template->buf == NULL ||
942                 task->pkt_template_orig->buf == NULL,
943                 "Failed to allocate %u bytes (in huge pages) for packet\n", task->max_frame_size);
944
945         PROX_PANIC(targ->pkt_size > task->max_frame_size,
946                 targ->pkt_size > ETHER_MAX_LEN + 2 * PROX_VLAN_TAG_SIZE - 4 ?
947                         "pkt_size too high and jumbo frames disabled" : "pkt_size > mtu");
948
949         rte_memcpy(task->pkt_template_orig[0].buf, targ->pkt_inline, targ->pkt_size);
950         task->pkt_template_orig[0].len = targ->pkt_size;
951         task_gen_reset_pkt_templates(task);
952         check_all_pkt_size(task, 1);
953         check_fields_in_bounds(task, task->pkt_template[0].len, 1);
954 }
955
956 static void task_init_gen_load_pcap(struct task_gen *task, struct task_args *targ)
957 {
958         const int socket_id = rte_lcore_to_socket_id(targ->lconf->id);
959         char err[PCAP_ERRBUF_SIZE];
960         uint32_t max_frame_size;
961         pcap_t *handle = pcap_open_offline(targ->pcap_file, err);
962         PROX_PANIC(handle == NULL, "Failed to open PCAP file: %s\n", err);
963
964         task->n_pkts = pcap_count_pkts(handle, &max_frame_size);
965         plogx_info("%u packets in pcap file '%s'\n", task->n_pkts, targ->pcap_file);
966         PROX_PANIC(max_frame_size > task->max_frame_size,
967                 max_frame_size > ETHER_MAX_LEN + 2 * PROX_VLAN_TAG_SIZE -4 ?
968                         "pkt_size too high and jumbo frames disabled" : "pkt_size > mtu");
969
970         if (targ->n_pkts)
971                 task->n_pkts = RTE_MIN(task->n_pkts, targ->n_pkts);
972         PROX_PANIC(task->n_pkts > MAX_TEMPLATE_INDEX, "Too many packets specified in pcap - increase MAX_TEMPLATE_INDEX\n");
973         plogx_info("Loading %u packets from pcap\n", task->n_pkts);
974         size_t mem_size = task->n_pkts * sizeof(*task->pkt_template);
975         task->pkt_template = prox_zmalloc(mem_size, socket_id);
976         task->pkt_template_orig = prox_zmalloc(mem_size, socket_id);
977         PROX_PANIC(task->pkt_template == NULL ||
978                    task->pkt_template_orig == NULL,
979                    "Failed to allocate %lu bytes (in huge pages) for pcap file\n", mem_size);
980
981         for (uint i = 0; i < task->n_pkts; i++) {
982                 task->pkt_template[i].buf = prox_zmalloc(max_frame_size, socket_id);
983                 task->pkt_template_orig[i].buf = prox_zmalloc(max_frame_size, socket_id);
984
985                 PROX_PANIC(task->pkt_template->buf == NULL ||
986                         task->pkt_template_orig->buf == NULL,
987                         "Failed to allocate %u bytes (in huge pages) for pcap file\n", task->max_frame_size);
988         }
989
990         pcap_read_pkts(handle, targ->pcap_file, task->n_pkts, task->pkt_template_orig, NULL);
991         pcap_close(handle);
992         task_gen_reset_pkt_templates(task);
993 }
994
995 static struct rte_mempool *task_gen_create_mempool(struct task_args *targ, uint16_t max_frame_size)
996 {
997         static char name[] = "gen_pool";
998         struct rte_mempool *ret;
999         const int sock_id = rte_lcore_to_socket_id(targ->lconf->id);
1000
1001         name[0]++;
1002         uint32_t mbuf_size = TX_MBUF_SIZE;
1003         if (max_frame_size + (unsigned)sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM > mbuf_size)
1004                 mbuf_size = max_frame_size + (unsigned)sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
1005         plog_info("\t\tCreating mempool with name '%s'\n", name);
1006         ret = rte_mempool_create(name, targ->nb_mbuf - 1, mbuf_size,
1007                                  targ->nb_cache_mbuf, sizeof(struct rte_pktmbuf_pool_private),
1008                                  rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, 0,
1009                                  sock_id, 0);
1010         PROX_PANIC(ret == NULL, "Failed to allocate dummy memory pool on socket %u with %u elements\n",
1011                    sock_id, targ->nb_mbuf - 1);
1012
1013         plog_info("\t\tMempool %p size = %u * %u cache %u, socket %d\n", ret,
1014                   targ->nb_mbuf - 1, mbuf_size, targ->nb_cache_mbuf, sock_id);
1015
1016         return ret;
1017 }
1018
1019 void task_gen_set_pkt_count(struct task_base *tbase, uint32_t count)
1020 {
1021         struct task_gen *task = (struct task_gen *)tbase;
1022
1023         task->pkt_count = count;
1024 }
1025
1026 int task_gen_set_pkt_size(struct task_base *tbase, uint32_t pkt_size)
1027 {
1028         struct task_gen *task = (struct task_gen *)tbase;
1029         int rc;
1030
1031         if ((rc = check_pkt_size(task, pkt_size, 0)) != 0)
1032                 return rc;
1033         if ((rc = check_fields_in_bounds(task, pkt_size, 0)) != 0)
1034                 return rc;
1035         task->pkt_template[0].len = pkt_size;
1036         return rc;
1037 }
1038
1039 void task_gen_set_rate(struct task_base *tbase, uint64_t bps)
1040 {
1041         struct task_gen *task = (struct task_gen *)tbase;
1042
1043         task->new_rate_bps = bps;
1044 }
1045
1046 void task_gen_reset_randoms(struct task_base *tbase)
1047 {
1048         struct task_gen *task = (struct task_gen *)tbase;
1049
1050         for (uint32_t i = 0; i < task->n_rands; ++i) {
1051                 task->rand[i].rand_mask = 0;
1052                 task->rand[i].fixed_bits = 0;
1053                 task->rand[i].rand_offset = 0;
1054         }
1055         task->n_rands = 0;
1056 }
1057
1058 int task_gen_set_value(struct task_base *tbase, uint32_t value, uint32_t offset, uint32_t len)
1059 {
1060         struct task_gen *task = (struct task_gen *)tbase;
1061
1062         for (size_t i = 0; i < task->n_pkts; ++i) {
1063                 uint32_t to_write = rte_cpu_to_be_32(value) >> ((4 - len) * 8);
1064                 uint8_t *dst = task->pkt_template[i].buf;
1065
1066                 rte_memcpy(dst + offset, &to_write, len);
1067         }
1068
1069         task_gen_pkt_template_recalc_all(task);
1070
1071         return 0;
1072 }
1073
1074 void task_gen_reset_values(struct task_base *tbase)
1075 {
1076         struct task_gen *task = (struct task_gen *)tbase;
1077
1078         task_gen_reset_pkt_templates_content(task);
1079 }
1080
1081 uint32_t task_gen_get_n_randoms(struct task_base *tbase)
1082 {
1083         struct task_gen *task = (struct task_gen *)tbase;
1084
1085         return task->n_rands;
1086 }
1087
1088 static void init_task_gen_pcap(struct task_base *tbase, struct task_args *targ)
1089 {
1090         struct task_gen_pcap *task = (struct task_gen_pcap *)tbase;
1091         const uint32_t sockid = rte_lcore_to_socket_id(targ->lconf->id);
1092         uint32_t max_frame_size;
1093
1094         task->loop = targ->loop;
1095         task->pkt_idx = 0;
1096         task->hz = rte_get_tsc_hz();
1097
1098         char err[PCAP_ERRBUF_SIZE];
1099         pcap_t *handle = pcap_open_offline(targ->pcap_file, err);
1100         PROX_PANIC(handle == NULL, "Failed to open PCAP file: %s\n", err);
1101
1102         task->n_pkts = pcap_count_pkts(handle, &max_frame_size);
1103         plogx_info("%u packets in pcap file '%s'\n", task->n_pkts, targ->pcap_file);
1104
1105         task->local_mbuf.mempool = task_gen_create_mempool(targ, max_frame_size);
1106
1107         PROX_PANIC(!strcmp(targ->pcap_file, ""), "No pcap file defined\n");
1108
1109         if (targ->n_pkts) {
1110                 plogx_info("Configured to load %u packets\n", targ->n_pkts);
1111                 if (task->n_pkts > targ->n_pkts)
1112                         task->n_pkts = targ->n_pkts;
1113         }
1114         PROX_PANIC(task->n_pkts > MAX_TEMPLATE_INDEX, "Too many packets specified in pcap - increase MAX_TEMPLATE_INDEX\n");
1115
1116         plogx_info("Loading %u packets from pcap\n", task->n_pkts);
1117
1118         size_t mem_size = task->n_pkts * (sizeof(*task->proto) + sizeof(*task->proto_tsc));
1119         uint8_t *mem = prox_zmalloc(mem_size, sockid);
1120
1121         PROX_PANIC(mem == NULL, "Failed to allocate %lu bytes (in huge pages) for pcap file\n", mem_size);
1122         task->proto = (struct pkt_template *) mem;
1123         task->proto_tsc = (uint64_t *)(mem + task->n_pkts * sizeof(*task->proto));
1124
1125         for (uint i = 0; i < targ->n_pkts; i++) {
1126                 task->proto[i].buf = prox_zmalloc(max_frame_size, sockid);
1127                 PROX_PANIC(task->proto[i].buf == NULL, "Failed to allocate %u bytes (in huge pages) for pcap file\n", max_frame_size);
1128         }
1129
1130         pcap_read_pkts(handle, targ->pcap_file, task->n_pkts, task->proto, task->proto_tsc);
1131         pcap_close(handle);
1132 }
1133
1134 static int task_gen_find_random_with_offset(struct task_gen *task, uint32_t offset)
1135 {
1136         for (uint32_t i = 0; i < task->n_rands; ++i) {
1137                 if (task->rand[i].rand_offset == offset) {
1138                         return i;
1139                 }
1140         }
1141
1142         return UINT32_MAX;
1143 }
1144
1145 int task_gen_add_rand(struct task_base *tbase, const char *rand_str, uint32_t offset, uint32_t rand_id)
1146 {
1147         struct task_gen *task = (struct task_gen *)tbase;
1148         uint32_t existing_rand;
1149
1150         if (rand_id == UINT32_MAX && task->n_rands == 64) {
1151                 plog_err("Too many randoms\n");
1152                 return -1;
1153         }
1154         uint32_t mask, fixed, len;
1155
1156         if (parse_random_str(&mask, &fixed, &len, rand_str)) {
1157                 plog_err("%s\n", get_parse_err());
1158                 return -1;
1159         }
1160         task->runtime_checksum_needed = 1;
1161
1162         existing_rand = task_gen_find_random_with_offset(task, offset);
1163         if (existing_rand != UINT32_MAX) {
1164                 plog_warn("Random at offset %d already set => overwriting len = %d %s\n", offset, len, rand_str);
1165                 rand_id = existing_rand;
1166                 task->rand[rand_id].rand_len = len;
1167                 task->rand[rand_id].rand_offset = offset;
1168                 task->rand[rand_id].rand_mask = mask;
1169                 task->rand[rand_id].fixed_bits = fixed;
1170                 return 0;
1171         }
1172
1173         task->rand[task->n_rands].rand_len = len;
1174         task->rand[task->n_rands].rand_offset = offset;
1175         task->rand[task->n_rands].rand_mask = mask;
1176         task->rand[task->n_rands].fixed_bits = fixed;
1177
1178         task->n_rands++;
1179         return 0;
1180 }
1181
1182 static void start(struct task_base *tbase)
1183 {
1184         struct task_gen *task = (struct task_gen *)tbase;
1185         task->pkt_queue_index = 0;
1186
1187         task_gen_reset_token_time(task);
1188         if (tbase->l3.tmaster) {
1189                 register_all_ip_to_ctrl_plane(task);
1190         }
1191
1192         /* TODO
1193            Handle the case when two tasks transmit to the same port
1194            and one of them is stopped. In that case ARP (requests or replies)
1195            might not be sent. Master will have to keep a list of rings.
1196            stop will have to de-register IP from ctrl plane.
1197            un-registration will remove the ring. when having more than
1198            one active rings, master can always use the first one
1199         */
1200 }
1201
1202 static void start_pcap(struct task_base *tbase)
1203 {
1204         struct task_gen_pcap *task = (struct task_gen_pcap *)tbase;
1205         /* When we start, the first packet is sent immediately. */
1206         task->last_tsc = rte_rdtsc() - task->proto_tsc[0];
1207         task->pkt_idx = 0;
1208 }
1209
1210 static void init_task_gen_early(struct task_args *targ)
1211 {
1212         uint8_t *generator_count = prox_sh_find_system("generator_count");
1213
1214         if (generator_count == NULL) {
1215                 generator_count = prox_zmalloc(sizeof(*generator_count), rte_lcore_to_socket_id(targ->lconf->id));
1216                 PROX_PANIC(generator_count == NULL, "Failed to allocate generator count\n");
1217                 prox_sh_add_system("generator_count", generator_count);
1218         }
1219         targ->generator_id = *generator_count;
1220         (*generator_count)++;
1221 }
1222
1223 static void init_task_gen(struct task_base *tbase, struct task_args *targ)
1224 {
1225         struct task_gen *task = (struct task_gen *)tbase;
1226
1227         task->packet_id_pos = targ->packet_id_pos;
1228
1229         struct prox_port_cfg *port = find_reachable_port(targ);
1230         // TODO: check that all reachable ports have the same mtu...
1231         if (port) {
1232                 task->cksum_offload = port->requested_tx_offload & (DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM);
1233                 task->port = port;
1234                 task->max_frame_size = port->mtu + ETHER_HDR_LEN + 2 * PROX_VLAN_TAG_SIZE;
1235         } else {
1236                 // Not generating to any port...
1237                 task->max_frame_size = ETHER_MAX_LEN;
1238         }
1239         task->local_mbuf.mempool = task_gen_create_mempool(targ, task->max_frame_size);
1240         PROX_PANIC(task->local_mbuf.mempool == NULL, "Failed to create mempool\n");
1241         task->pkt_idx = 0;
1242         task->hz = rte_get_tsc_hz();
1243         task->lat_pos = targ->lat_pos;
1244         task->accur_pos = targ->accur_pos;
1245         task->sig_pos = targ->sig_pos;
1246         task->sig = targ->sig;
1247         task->new_rate_bps = targ->rate_bps;
1248
1249         /*
1250          * For tokens, use 10 Gbps as base rate
1251          * Scripts can then use speed command, with speed=100 as 10 Gbps and speed=400 as 40 Gbps
1252          * Script can query prox "port info" command to find out the port link speed to know
1253          * at which rate to start. Note that virtio running on OVS returns 10 Gbps, so a script has
1254          * probably also to check the driver (as returned by the same "port info" command.
1255          */
1256         struct token_time_cfg tt_cfg = token_time_cfg_create(1250000000, rte_get_tsc_hz(), -1);
1257         token_time_init(&task->token_time, &tt_cfg);
1258
1259         init_task_gen_seeds(task);
1260
1261         task->min_bulk_size = targ->min_bulk_size;
1262         task->max_bulk_size = targ->max_bulk_size;
1263         if (task->min_bulk_size < 1)
1264                 task->min_bulk_size = 1;
1265         if (task->max_bulk_size < 1)
1266                 task->max_bulk_size = 64;
1267         PROX_PANIC(task->max_bulk_size > 64, "max_bulk_size higher than 64\n");
1268         PROX_PANIC(task->max_bulk_size < task->min_bulk_size, "max_bulk_size must be > than min_bulk_size\n");
1269
1270         task->pkt_count = -1;
1271         task->lat_enabled = targ->lat_enabled;
1272         task->runtime_flags = targ->runtime_flags;
1273         PROX_PANIC((task->lat_pos || task->accur_pos) && !task->lat_enabled, "lat not enabled by lat pos or accur pos configured\n");
1274
1275         task->generator_id = targ->generator_id;
1276         plog_info("\tGenerator id = %d\n", task->generator_id);
1277
1278         // Allocate array holding bytes to tsc for supported frame sizes
1279         task->bytes_to_tsc = prox_zmalloc(task->max_frame_size * MAX_PKT_BURST * sizeof(task->bytes_to_tsc[0]), rte_lcore_to_socket_id(targ->lconf->id));
1280         PROX_PANIC(task->bytes_to_tsc == NULL,
1281                 "Failed to allocate %u bytes (in huge pages) for bytes_to_tsc\n", task->max_frame_size);
1282
1283         // task->port->max_link_speed reports the maximum, non negotiated ink speed in Mbps e.g. 40k for a 40 Gbps NIC.
1284         // It can be UINT32_MAX (virtual devices or not supported by DPDK < 16.04)
1285         uint64_t bytes_per_hz = UINT64_MAX;
1286         if ((task->port) && (task->port->max_link_speed != UINT32_MAX)) {
1287                 bytes_per_hz = task->port->max_link_speed * 125000L;
1288                 plog_info("\tPort %u: max link speed is %ld Mbps\n",
1289                         (uint8_t)(task->port - prox_port_cfg), 8 * bytes_per_hz / 1000000);
1290         }
1291         // There are cases where hz estimate might be slighly over-estimated
1292         // This results in too much extrapolation
1293         // Only account for 99% of extrapolation to handle cases with up to 1% error clocks
1294         for (unsigned int i = 0; i < task->max_frame_size * MAX_PKT_BURST ; i++) {
1295                 if (bytes_per_hz == UINT64_MAX)
1296                         task->bytes_to_tsc[i] = 0;
1297                 else
1298                         task->bytes_to_tsc[i] = (task->hz * i * 0.99) / bytes_per_hz;
1299         }
1300
1301         if (!strcmp(targ->pcap_file, "")) {
1302                 plog_info("\tUsing inline definition of a packet\n");
1303                 task_init_gen_load_pkt_inline(task, targ);
1304         } else {
1305                 plog_info("Loading from pcap %s\n", targ->pcap_file);
1306                 task_init_gen_load_pcap(task, targ);
1307         }
1308
1309         PROX_PANIC(((targ->nb_txrings == 0) && (targ->nb_txports == 0)), "Gen mode requires a tx ring or a tx port");
1310         if ((targ->flags & DSF_KEEP_SRC_MAC) == 0) {
1311                 uint8_t *src_addr = prox_port_cfg[tbase->tx_params_hw.tx_port_queue->port].eth_addr.addr_bytes;
1312                 for (uint32_t i = 0; i < task->n_pkts; ++i) {
1313                         rte_memcpy(&task->pkt_template[i].buf[6], src_addr, 6);
1314                 }
1315         }
1316         memcpy(&task->src_mac, &prox_port_cfg[task->base.tx_params_hw.tx_port_queue->port].eth_addr, sizeof(struct ether_addr));
1317         for (uint32_t i = 0; i < targ->n_rand_str; ++i) {
1318                 PROX_PANIC(task_gen_add_rand(tbase, targ->rand_str[i], targ->rand_offset[i], UINT32_MAX),
1319                            "Failed to add random\n");
1320         }
1321 }
1322
1323 static struct task_init task_init_gen = {
1324         .mode_str = "gen",
1325         .init = init_task_gen,
1326         .handle = handle_gen_bulk,
1327         .start = start,
1328         .early_init = init_task_gen_early,
1329 #ifdef SOFT_CRC
1330         // For SOFT_CRC, no offload is needed. If both NOOFFLOADS and NOMULTSEGS flags are set the
1331         // vector mode is used by DPDK, resulting (theoretically) in higher performance.
1332         .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX | TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS,
1333 #else
1334         .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX,
1335 #endif
1336         .size = sizeof(struct task_gen)
1337 };
1338
1339 static struct task_init task_init_gen_l3 = {
1340         .mode_str = "gen",
1341         .sub_mode_str = "l3",
1342         .init = init_task_gen,
1343         .handle = handle_gen_bulk,
1344         .start = start,
1345         .early_init = init_task_gen_early,
1346 #ifdef SOFT_CRC
1347         // For SOFT_CRC, no offload is needed. If both NOOFFLOADS and NOMULTSEGS flags are set the
1348         // vector mode is used by DPDK, resulting (theoretically) in higher performance.
1349         .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX | TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS,
1350 #else
1351         .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX,
1352 #endif
1353         .size = sizeof(struct task_gen)
1354 };
1355
1356 static struct task_init task_init_gen_pcap = {
1357         .mode_str = "gen",
1358         .sub_mode_str = "pcap",
1359         .init = init_task_gen_pcap,
1360         .handle = handle_gen_pcap_bulk,
1361         .start = start_pcap,
1362         .early_init = init_task_gen_early,
1363 #ifdef SOFT_CRC
1364         .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX | TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS,
1365 #else
1366         .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX,
1367 #endif
1368         .size = sizeof(struct task_gen_pcap)
1369 };
1370
1371 __attribute__((constructor)) static void reg_task_gen(void)
1372 {
1373         reg_task(&task_init_gen);
1374         reg_task(&task_init_gen_l3);
1375         reg_task(&task_init_gen_pcap);
1376 }