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