28#include <odp/helper/odph_api.h>
29#include <pktio_common.h>
31#if ODP_THREAD_COUNT_MAX > 33
35#define MAX_THREADS ODP_THREAD_COUNT_MAX
38#define MAX_WORKERS (MAX_THREADS - 1)
47#define MAX_ALLOC_PACKETS (64 * 1024)
50#define MAX_PKTIO_NAME 255
54#define ETH_TYPE_QINQ 0x88a8
56#define RAND_16BIT_WORDS MAX_BINS
58#define MAX_RAND_RETRIES 1000
59#define MAX_HDR_NAME_LEN 32
60#define MAX_HDR_FIELDS 16
61#define MAX_HDR_VALUE_SZ 8
62#define TOKEN_DELIMITER ","
63#define FIELD_DELIMITER ":"
73#define MIN_RX_PACKETS_CI 160
76#define TS_MAGIC 0xff88ee99ddaaccbb
87ODP_STATIC_ASSERT(MAX_PKTIOS <= UINT8_MAX,
"Interface index must fit into uint8_t\n");
90 char name[MAX_HDR_NAME_LEN + 1];
97 hdr_field_t fields[MAX_HDR_FIELDS];
102typedef struct test_options_t {
105 uint64_t update_msec;
112 uint8_t use_rand_pkt_len;
114 uint32_t rand_pkt_len_min;
115 uint32_t rand_pkt_len_max;
116 uint32_t rand_pkt_len_bins;
128 uint32_t wait_start_sec;
130 uint32_t num_custom_l3;
133 uint32_t payload_offset;
134 uint32_t max_payload_len;
155 char pktio_name[MAX_PKTIOS][MAX_PKTIO_NAME + 1];
163typedef struct thread_arg_t {
183 uint64_t rx_timeouts;
186 uint64_t rx_lat_nsec;
187 uint64_t rx_lat_min_nsec;
188 uint64_t rx_lat_max_nsec;
189 uint64_t rx_lat_packets;
191 uint64_t tx_timeouts;
206typedef struct test_global_t {
207 test_options_t test_options;
213 odph_thread_t thread_tbl[MAX_THREADS];
214 thread_stat_t stat[MAX_THREADS];
215 thread_arg_t thread_arg[MAX_THREADS];
218 odph_ethaddr_t eth_src;
219 odph_ethaddr_t eth_dst;
233 uint32_t len_bin[MAX_BINS];
236 uint16_t rand_data[MAX_THREADS][RAND_16BIT_WORDS];
255static test_global_t *test_global;
257static void print_usage(
void)
260 "ODP packet generator\n"
262 "Usage: odp_packet_gen [options]\n"
265 " -i, --interface <name> Packet IO interfaces. Comma-separated list of\n"
266 " interface names (no spaces) e.g. eth0,eth1.\n"
267 " At least one interface is required.\n"
269 printf(
" Optional:\n"
270 " -e, --eth_dst <mac> Destination MAC address. Comma-separated list of\n"
271 " addresses (no spaces), one address per packet IO\n"
272 " interface e.g. AA:BB:CC:DD:EE:FF,11:22:33:44:55:66\n"
273 " Default per interface: 02:00:00:A0:B0:CX, where X = 0,1,...\n"
274 " -v, --vlan <tpid:tci> VLAN configuration. Comma-separated list of VLAN TPID:TCI\n"
275 " values in hexadecimal, starting from the outer most VLAN.\n"
277 " VLAN 200 (decimal): 0x8100:c8\n"
278 " Double tagged VLANs 1 and 2: 0x88a8:1,0x8100:2\n"
279 " -r, --num_rx Number of receive threads. Default: 1\n"
280 " -t, --num_tx Number of transmit threads. Default: 1\n"
281 " -T, --lso <options> Transmit packets with Large Send Offload (LSO). Specify\n"
282 " LSO options as comma-separated list (no spaces) in\n"
283 " format: protocol,payload_offset(B),max_payload_len(B). E.g.:\n"
285 " In case of ODP_LSO_PROTO_CUSTOM the list is extended by\n"
286 " up to %d custom modification options. For ODP_LSO_ADD_*\n"
287 " operations the format is:\n"
288 " mod_op:offset(B):size(B)\n"
289 " For ODP_LSO_WRITE_BITS the format is:\n"
290 " mod_op:offset(B):size(B):fm:fv:mm:mv:lm:lv\n"
291 " where size must be 1 and fm/fv, mm/mv, lm/lv are the\n"
292 " mask/value byte pairs to write to the first, middle\n"
293 " and last segments respectively. Custom modification\n"
294 " options are separated by commas. E.g.:\n"
295 " 2,22,1500,0:19:1\n"
296 " 2,22,1500,3:19:1:0xff:0x80:0xff:0x00:0xff:0x40\n"
297 " Supported protocols:\n"
298 " 0: ODP_LSO_PROTO_IPV4\n"
299 " 1: ODP_LSO_PROTO_TCP_IPV4\n"
300 " 2: ODP_LSO_PROTO_CUSTOM\n"
301 " Custom modification options:\n"
302 " 0: ODP_LSO_ADD_SEGMENT_NUM\n"
303 " 1: ODP_LSO_ADD_PAYLOAD_LEN\n"
304 " 2: ODP_LSO_ADD_PAYLOAD_OFFSET\n"
305 " 3: ODP_LSO_WRITE_BITS\n"
306 " Depending on the implementation, all listed LSO options\n"
307 " may not be always supported.\n"
308 " -n, --num_pkt Number of packets in the pool. Default: 1000\n"
309 " -l, --len Packet length. Default: 512\n"
310 " -L, --len_range <min,max,bins>\n"
311 " Random packet length. Specify the minimum and maximum\n"
312 " packet lengths and the number of bins. To reduce pool size\n"
313 " requirement the length range can be divided into even sized\n"
314 " bins (max %u). Min and max size packets are always used and included\n"
315 " into the number of bins (bins >= 2). Bin value of 0 means\n"
316 " that each packet length is used. Comma-separated (no spaces).\n"
317 " Overrides standard packet length option.\n"
318 " -D, --direct_rx Direct input mode (default: 0)\n"
319 " 0: Use scheduler for packet input\n"
320 " 1: Poll packet input in direct mode\n",
322 printf(
" -m, --tx_mode Transmit mode (default 1):\n"
323 " 0: Re-send packets with don't free option\n"
324 " 1: Send static packet references. Some features may\n"
325 " not be available with references.\n"
326 " 2: Send copies of packets\n"
327 " -M, --mtu <len> Interface MTU in bytes.\n"
328 " -b, --burst_size Transmit burst size. Default: 8\n"
329 " -x, --bursts Number of bursts per one transmit round. Default: 1\n"
330 " -g, --gap Gap between transmit rounds in nsec. Default: 1000000\n"
331 " Transmit packet rate per interface:\n"
332 " num_tx * burst_size * bursts * (10^9 / gap)\n"
333 " -s, --ipv4_src IPv4 source address. Default: 192.168.0.1\n"
334 " -d, --ipv4_dst IPv4 destination address. Default: 192.168.0.2\n"
335 " -o, --src_port UDP/TCP source port. Default: 10000\n"
336 " -p, --dst_port UDP/TCP destination port. Default: 20000\n"
337 " -N, --proto L4 protocol. Default: 0\n"
341 " -P, --promisc_mode Enable promiscuous mode.\n"
342 " -a, --latency Calculate latency. Cannot be used with packet\n"
343 " references (see \"--tx_mode\").\n"
344 " -c, --c_mode <counts> Counter mode for incrementing UDP/TCP port numbers.\n"
345 " Specify the number of port numbers used starting from\n"
346 " src_port/dst_port. Comma-separated (no spaces) list of\n"
347 " count values: <src_port count>,<dst_port count>\n"
348 " Default value: 0,0\n"
349 " -C, --no_udp_checksum Do not calculate UDP SW checksum. Instead, set it to\n"
350 " zero in every packet, this may be overridden by\n"
351 " '--checksum_offload' option.\n"
352 " -X, --checksum_offload Enable L4 checksum offloads: checksums are checked\n"
353 " at input and inserted at output.\n"
354 " -A, --no_payload_fill Do not fill payload. By default, payload is filled\n"
355 " with a pattern until the end of first packet\n"
357 " -q, --quit Quit after this many transmit rounds.\n"
358 " Default: 0 (don't quit)\n"
359 " -u, --update_stat <msec> Update and print statistics every <msec> milliseconds.\n"
360 " 0: Don't print statistics periodically (default)\n"
361 " -h, --help This help\n"
362 " -w, --wait <sec> Wait up to <sec> seconds for network links to be up.\n"
363 " Default: 0 (don't check link status)\n");
364 printf(
" -U, --custom_l3 <definition>\n"
365 " Define a custom L3 header for packets. This\n"
366 " overrides the default IP header and any related\n"
367 " options. Elements should be comma-separated (no\n"
368 " spaces). Definition should begin with an EtherType\n"
369 " value, followed by field definitions. Each field\n"
370 " should be in the format\n"
371 " <name>:<length(B)>:<value>:<diff>, i.e.\n"
372 " colon-separated (no spaces). Name/length/value\n"
373 " elements are self-explanatory, the 'diff' element\n"
374 " defines a value that's added (subtracted if\n"
375 " negative) to the 'value' element in successive\n"
376 " packets. Fields are used in the order they are\n"
377 " defined in the string. E.g.:\n\n"
378 " 0x900,a:4:0xaaaaaaaa:1,b:1:0xff:-2\n\n"
379 " would result in a header of EtherType 0x900 with\n"
380 " fields 'a' and 'b' of values and lengths\n"
381 " '0xaaaaaaaa' (4 bytes) and '0xff' (1 byte)\n"
382 " respectively. Value 1 is added to '0xaaaaaaaa' and\n"
383 " -2 to '0xff' in successive packets. EtherType and\n"
384 " 'value' elements should be given in hexadecimals.\n"
385 " Field names are only for information and debugging\n"
386 " purposes. Maximum amount of fields supported is %u,\n"
387 " maximum name length of a field is %u and maximum\n"
388 " value size is %u bytes.\n"
389 " -W, --wait_start <sec> Wait <sec> seconds before starting traffic. Default: 0\n"
390 "\n", MAX_HDR_FIELDS, MAX_HDR_NAME_LEN, MAX_HDR_VALUE_SZ);
393static int parse_vlan(
const char *str, test_global_t *global)
395 struct vlan_hdr *vlan;
396 const char *start = str;
399 intptr_t str_len = strlen(str);
401 while (num_vlan < MAX_VLANS) {
402 vlan = &global->test_options.vlan[num_vlan];
406 vlan->tpid = strtoul(start, &end, 16);
412 if (start - str >= str_len)
417 vlan->tci = strtoul(start, &end, 16);
425 if (start - str >= str_len)
432static inline uint64_t bswap(uint64_t in, uint32_t len)
440 for (uint32_t i = 0; i < len; i++) {
441 byte = (in >> (8 * i)) & 0xff;
442 result |= ((uint64_t)
byte << (8 * (len - 1 - i)));
448static odp_bool_t parse_custom_fields(
const char *optarg, test_options_t *opts)
450 char *tmp_str = strdup(optarg), *tmp;
451 uint32_t num_fields = 0;
452 char name[MAX_HDR_NAME_LEN + 1];
462 tmp = strtok(tmp_str, TOKEN_DELIMITER);
469 opts->custom_l3.eth_type = strtoul(tmp, NULL, 16);
470 tmp = strtok(NULL, TOKEN_DELIMITER);
473 if (num_fields == MAX_HDR_FIELDS) {
474 ODPH_ERR(
"Invalid custom header, too many fields: %u\n", num_fields + 1);
479 ret = sscanf(tmp,
"%" S(MAX_HDR_NAME_LEN)
"[^" FIELD_DELIMITER
"]" FIELD_DELIMITER
480 "%u" FIELD_DELIMITER
"%" PRIx64 FIELD_DELIMITER
"%" PRIi64
"", name,
481 &len, &value, &diff);
484 ODPH_ERR(
"Invalid custom header, bad field format\n");
489 if (len > MAX_HDR_VALUE_SZ) {
490 ODPH_ERR(
"Invalid custom header, field length too long: %u\n", len);
495 hdr = &opts->custom_l3.fields[num_fields];
496 odph_strcpy(hdr->name, name, MAX_HDR_NAME_LEN + 1);
500 opts->custom_l3.tot_len += len;
502 tmp = strtok(NULL, TOKEN_DELIMITER);
505 opts->num_custom_l3 = num_fields;
511static odp_bool_t parse_lso_fields(
const char *optarg, test_options_t *opts)
513 char *tmp_str = strdup(optarg), *tmp;
514 uint8_t num_custom = 0;
515 uint32_t proto, mod_op, offset, size;
521 if (tmp_str == NULL) {
522 ODPH_ERR(
"Error: strdup() failed\n");
528 tmp = strtok(tmp_str, TOKEN_DELIMITER);
530 ODPH_ERR(
"Error: Unable to parse LSO protocol\n");
535 proto = strtoul(tmp, NULL, 0);
548 ODPH_ERR(
"Error: Invalid LSO protocol: %u\n", proto);
553 tmp = strtok(NULL, TOKEN_DELIMITER);
555 ODPH_ERR(
"Error: Unable to parse LSO payload offset\n");
559 opts->lso.payload_offset = strtoul(tmp, NULL, 0);
561 tmp = strtok(NULL, TOKEN_DELIMITER);
563 ODPH_ERR(
"Error: Unable to parse LSO max payload length\n");
567 opts->lso.max_payload_len = strtoul(tmp, NULL, 0);
569 tmp = strtok(NULL, TOKEN_DELIMITER);
572 ODPH_ERR(
"Error: Too many custom LSO operations (max %u)\n",
578 ret = sscanf(tmp,
"%" PRIu32
"" FIELD_DELIMITER
579 "%" PRIu32
"" FIELD_DELIMITER
"%" PRIu32
"",
580 &mod_op, &offset, &size);
583 ODPH_ERR(
"Error: Invalid custom LSO operation, bad field format\n");
596 opts->lso.param.custom.field[num_custom].mod_op =
603 ODPH_ERR(
"Error: Invalid custom LSO operation: %" PRIu32
"\n", mod_op);
608 opts->lso.param.custom.field[num_custom].offset = offset;
610 if (mod_op == 3 && size != 1) {
611 ODPH_ERR(
"Error: ODP_LSO_WRITE_BITS requires size of 1 byte"
612 " (got %" PRIu32
")\n", size);
615 }
else if (mod_op != 3 && size != 1 && size != 2 && size != 4 && size != 8) {
616 ODPH_ERR(
"Error: Invalid custom field size: %" PRIu32
"\n", size);
621 opts->lso.param.custom.field[num_custom].size = size;
625 int32_t f_mask, f_val, m_mask, m_val, l_mask, l_val;
627 ret = sscanf(tmp,
"%*u" FIELD_DELIMITER
"%*u" FIELD_DELIMITER
"%*u"
628 FIELD_DELIMITER
"%" SCNi32 FIELD_DELIMITER
"%" SCNi32
629 FIELD_DELIMITER
"%" SCNi32 FIELD_DELIMITER
"%" SCNi32
630 FIELD_DELIMITER
"%" SCNi32 FIELD_DELIMITER
"%" SCNi32,
631 &f_mask, &f_val, &m_mask, &m_val, &l_mask, &l_val);
634 ODPH_ERR(
"Error: ODP_LSO_WRITE_BITS requires 6 mask/value bytes, "
635 "parsed: %d\n", ret);
640 if (f_mask < 0 || f_mask > UINT8_MAX || f_val < 0 || f_val > UINT8_MAX ||
641 m_mask < 0 || m_mask > UINT8_MAX || m_val < 0 || m_val > UINT8_MAX ||
642 l_mask < 0 || l_mask > UINT8_MAX || l_val < 0 || l_val > UINT8_MAX) {
643 ODPH_ERR(
"Error: ODP_LSO_WRITE_BITS mask/value byte out of "
649 opts->lso.param.custom.field[num_custom].write_bits.first_seg.mask[0] =
651 opts->lso.param.custom.field[num_custom].write_bits.first_seg.value[0] =
653 opts->lso.param.custom.field[num_custom].write_bits.middle_seg.mask[0] =
655 opts->lso.param.custom.field[num_custom].write_bits.middle_seg.value[0] =
657 opts->lso.param.custom.field[num_custom].write_bits.last_seg.mask[0] =
659 opts->lso.param.custom.field[num_custom].write_bits.last_seg.value[0] =
664 tmp = strtok(NULL, TOKEN_DELIMITER);
668 ODPH_ERR(
"Error: Custom LSO protocol requires at least one custom field\n");
673 opts->lso.param.custom.num_custom = num_custom;
674 opts->lso.enabled =
true;
682static int init_bins(test_global_t *global)
684 uint32_t i, bin_size;
685 test_options_t *test_options = &global->test_options;
686 uint32_t num_bins = test_options->rand_pkt_len_bins;
687 uint32_t len_min = test_options->rand_pkt_len_min;
688 uint32_t len_max = test_options->rand_pkt_len_max;
689 uint32_t num_bytes = len_max - len_min + 1;
691 if (len_max <= len_min) {
692 ODPH_ERR(
"Error: Bad max packet length\n");
697 num_bins = num_bytes;
699 if (num_bins == 1 || num_bins > MAX_BINS || num_bins > num_bytes) {
700 ODPH_ERR(
"Error: Bad number of packet length bins: %u\n", num_bins);
704 bin_size = (len_max - len_min + 1) / (num_bins - 1);
707 for (i = 0; i < num_bins - 1; i++)
708 global->len_bin[i] = len_min + (i * bin_size);
711 global->len_bin[i] = len_max;
712 global->num_bins = num_bins;
717static int parse_options(
int argc,
char *argv[], test_global_t *global)
719 int opt, i, len, str_len, port;
720 unsigned long int count;
721 uint32_t min_packets, num_tx_pkt, num_tx_alloc, pkt_len, req_len, val, bins;
722 char *name, *str, *end;
723 test_options_t *test_options = &global->test_options;
725 uint8_t default_eth_dst[6] = {0x02, 0x00, 0x00, 0xa0, 0xb0, 0xc0};
727 static const struct option longopts[] = {
728 {
"interface", required_argument, NULL,
'i'},
729 {
"eth_dst", required_argument, NULL,
'e'},
730 {
"num_rx", required_argument, NULL,
'r'},
731 {
"num_tx", required_argument, NULL,
't'},
732 {
"lso", required_argument, NULL,
'T'},
733 {
"num_pkt", required_argument, NULL,
'n'},
734 {
"proto", required_argument, NULL,
'N'},
735 {
"len", required_argument, NULL,
'l'},
736 {
"len_range", required_argument, NULL,
'L'},
737 {
"direct_rx", required_argument, NULL,
'D'},
738 {
"tx_mode", required_argument, NULL,
'm'},
739 {
"burst_size", required_argument, NULL,
'b'},
740 {
"bursts", required_argument, NULL,
'x'},
741 {
"gap", required_argument, NULL,
'g'},
742 {
"vlan", required_argument, NULL,
'v'},
743 {
"ipv4_src", required_argument, NULL,
's'},
744 {
"ipv4_dst", required_argument, NULL,
'd'},
745 {
"src_port", required_argument, NULL,
'o'},
746 {
"dst_port", required_argument, NULL,
'p'},
747 {
"promisc_mode", no_argument, NULL,
'P'},
748 {
"latency", no_argument, NULL,
'a'},
749 {
"c_mode", required_argument, NULL,
'c'},
750 {
"no_udp_checksum", no_argument, NULL,
'C'},
751 {
"checksum_offload", no_argument, NULL,
'X'},
752 {
"no_payload_fill", no_argument, NULL,
'A'},
753 {
"mtu", required_argument, NULL,
'M'},
754 {
"quit", required_argument, NULL,
'q'},
755 {
"wait", required_argument, NULL,
'w'},
756 {
"wait_start", required_argument, NULL,
'W'},
757 {
"update_stat", required_argument, NULL,
'u'},
758 {
"custom_l3", required_argument, NULL,
'U'},
759 {
"help", no_argument, NULL,
'h'},
763 static const char *shortopts =
"+i:e:r:t:T:n:N:l:L:D:m:M:b:x:g:v:s:d:o:"
764 "p:c:CXAq:u:w:W:PaU:h";
766 test_options->num_pktio = 0;
767 test_options->num_rx = 1;
768 test_options->num_tx = 1;
769 test_options->num_pkt = 1000;
770 test_options->pkt_len = 512;
771 test_options->use_rand_pkt_len = 0;
772 test_options->direct_rx = 0;
773 test_options->tx_mode = TX_MODE_REF;
774 test_options->burst_size = 8;
775 test_options->bursts = 1;
776 test_options->gap_nsec = 1000000;
777 test_options->num_vlan = 0;
778 test_options->promisc_mode = 0;
779 test_options->calc_latency = 0;
780 test_options->calc_cs = 1;
781 test_options->cs_offload = 0;
782 test_options->fill_pl = 1;
783 odph_strcpy(test_options->ipv4_src_s,
"192.168.0.1",
784 sizeof(test_options->ipv4_src_s));
785 odph_strcpy(test_options->ipv4_dst_s,
"192.168.0.2",
786 sizeof(test_options->ipv4_dst_s));
787 if (odph_ipv4_addr_parse(&test_options->ipv4_src, test_options->ipv4_src_s)) {
788 ODPH_ERR(
"Address parse failed\n");
791 if (odph_ipv4_addr_parse(&test_options->ipv4_dst, test_options->ipv4_dst_s)) {
792 ODPH_ERR(
"Address parse failed\n");
795 test_options->src_port = 10000;
796 test_options->dst_port = 20000;
797 test_options->c_mode.src_port = 0;
798 test_options->c_mode.dst_port = 0;
799 test_options->quit = 0;
800 test_options->update_msec = 0;
801 test_options->wait_sec = 0;
802 test_options->wait_start_sec = 0;
803 test_options->mtu = 0;
804 test_options->l4_proto = L4_PROTO_UDP;
805 test_options->lso.enabled =
false;
807 for (i = 0; i < MAX_PKTIOS; i++) {
808 memcpy(global->pktio[i].eth_dst.addr, default_eth_dst, 6);
809 global->pktio[i].eth_dst.addr[5] += i;
813 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
822 str_len = strlen(str);
824 while (str_len > 0) {
825 len = strcspn(str,
",");
828 if (i == MAX_PKTIOS) {
829 ODPH_ERR(
"Error: Too many interfaces\n");
834 if (len > MAX_PKTIO_NAME) {
835 ODPH_ERR(
"Error: Too long interface name %s\n", str);
840 name = test_options->pktio_name[i];
841 memcpy(name, str, len);
846 test_options->num_pktio = i;
852 str_len = strlen(str);
854 while (str_len > 0) {
855 odph_ethaddr_t *dst = &global->pktio[i].eth_dst;
857 len = strcspn(str,
",");
860 if (i == MAX_PKTIOS) {
861 ODPH_ERR(
"Error: Too many MAC addresses\n");
866 if (odph_eth_addr_parse(dst, str)) {
867 ODPH_ERR(
"Error: Bad MAC address: %s\n", str);
878 if (port < 0 || port > UINT16_MAX) {
879 ODPH_ERR(
"Error: Bad source port: %d\n", port);
883 test_options->src_port = port;
887 if (port < 0 || port > UINT16_MAX) {
888 ODPH_ERR(
"Error: Bad destination port: %d\n", port);
892 test_options->dst_port = port;
895 test_options->promisc_mode = 1;
898 test_options->calc_latency = 1;
901 test_options->num_rx = atoi(optarg);
904 test_options->num_tx = atoi(optarg);
907 if (!parse_lso_fields(optarg, test_options))
911 test_options->num_pkt = atoi(optarg);
914 test_options->l4_proto = atoi(optarg);
917 test_options->pkt_len = atoi(optarg);
920 pkt_len = strtoul(optarg, &end, 0);
921 test_options->rand_pkt_len_min = pkt_len;
923 pkt_len = strtoul(end, &str, 0);
924 test_options->rand_pkt_len_max = pkt_len;
926 val = strtoul(str, NULL, 0);
927 test_options->rand_pkt_len_bins = val;
928 test_options->use_rand_pkt_len = 1;
931 test_options->direct_rx = atoi(optarg);
934 test_options->tx_mode = atoi(optarg);
937 test_options->mtu = atoi(optarg);
940 test_options->burst_size = atoi(optarg);
943 test_options->bursts = atoi(optarg);
946 test_options->gap_nsec = atoll(optarg);
949 test_options->num_vlan = parse_vlan(optarg, global);
950 if (test_options->num_vlan == 0) {
951 ODPH_ERR(
"Error: Did not find any VLANs\n");
956 if (odph_ipv4_addr_parse(&test_options->ipv4_src,
958 ODPH_ERR(
"Error: Bad IPv4 source address: %s\n", optarg);
961 odph_strcpy(test_options->ipv4_src_s, optarg,
962 sizeof(test_options->ipv4_src_s));
965 if (odph_ipv4_addr_parse(&test_options->ipv4_dst,
967 ODPH_ERR(
"Error: Bad IPv4 destination address: %s\n", optarg);
970 odph_strcpy(test_options->ipv4_dst_s, optarg,
971 sizeof(test_options->ipv4_dst_s));
974 count = strtoul(optarg, &end, 0);
975 test_options->c_mode.src_port = count;
978 count = strtoul(end, NULL, 0);
979 test_options->c_mode.dst_port = count;
982 test_options->calc_cs = 0;
985 test_options->cs_offload = 1;
988 test_options->fill_pl = 0;
991 test_options->quit = atoll(optarg);
994 test_options->update_msec = atoll(optarg);
997 test_options->wait_sec = atoi(optarg);
1000 test_options->wait_start_sec = atoi(optarg);
1003 if (!parse_custom_fields(optarg, test_options))
1019 if (test_options->num_pktio == 0) {
1020 ODPH_ERR(
"Error: At least one packet IO interface is needed.\n");
1021 ODPH_ERR(
" Use -i <name> to specify interfaces.\n");
1025 if (test_options->num_rx < 1 && test_options->num_tx < 1) {
1026 ODPH_ERR(
"Error: At least one rx or tx thread needed.\n");
1030 test_options->num_cpu = test_options->num_rx + test_options->num_tx;
1032 if (test_options->num_cpu > MAX_WORKERS) {
1033 ODPH_ERR(
"Error: Too many worker threads\n");
1037 num_tx_pkt = test_options->burst_size * test_options->bursts;
1038 global->num_tx_pkt = num_tx_pkt;
1040 if (num_tx_pkt == 0) {
1041 ODPH_ERR(
"Error: Bad number of tx packets: %u\n", num_tx_pkt);
1045 if (test_options->use_rand_pkt_len) {
1046 if (init_bins(global))
1050 bins = global->num_bins ? global->num_bins : 1;
1051 num_tx_alloc = num_tx_pkt * bins;
1052 if (num_tx_alloc > MAX_ALLOC_PACKETS) {
1053 ODPH_ERR(
"Error: Too many tx packets: %u\n", num_tx_alloc);
1059 min_packets = test_options->num_pktio * test_options->num_tx * num_tx_alloc;
1060 min_packets += test_options->num_tx * test_options->burst_size;
1061 min_packets += test_options->num_pktio * test_options->num_rx * test_options->burst_size;
1063 if (test_options->num_pkt < min_packets) {
1064 ODPH_ERR(
"Error: Pool needs to have at least %u packets\n", min_packets);
1068 if (test_options->calc_latency && test_options->tx_mode == TX_MODE_REF) {
1069 ODPH_ERR(
"Error: Latency test is not supported with packet references (--tx_mode 1)\n");
1072 if (test_options->calc_latency && (test_options->num_rx < 1 || test_options->num_tx < 1)) {
1073 ODPH_ERR(
"Error: Latency test requires both rx and tx threads\n");
1077 if (test_options->gap_nsec) {
1078 double gap_hz = 1000000000.0 / test_options->gap_nsec;
1081 ODPH_ERR(
"\nWARNING: Burst gap exceeds time counter resolution "
1086 if (global->num_bins) {
1087 if (num_tx_pkt > global->num_bins && num_tx_pkt % global->num_bins)
1088 ODPH_ERR(
"\nWARNING: Transmit packet count is not evenly divisible into packet length bins.\n\n");
1090 if (num_tx_pkt < global->num_bins)
1091 ODPH_ERR(
"\nWARNING: Not enough packets for every packet length bin.\n\n");
1094 if (test_options->c_mode.dst_port && num_tx_pkt % test_options->c_mode.dst_port)
1095 ODPH_ERR(
"\nWARNING: Transmit packet count is not evenly divisible by destination port count.\n\n");
1097 if (test_options->c_mode.src_port && num_tx_pkt % test_options->c_mode.src_port)
1098 ODPH_ERR(
"\nWARNING: Transmit packet count is not evenly divisible by source port count.\n\n");
1100 if (test_options->l4_proto != L4_PROTO_TCP && test_options->l4_proto != L4_PROTO_UDP &&
1101 test_options->l4_proto != L4_PROTO_NONE) {
1102 ODPH_ERR(
"Error: Invalid L4 protocol: %" PRIu8
"\n", test_options->l4_proto);
1105 if (test_options->l4_proto == L4_PROTO_TCP && test_options->tx_mode != TX_MODE_COPY) {
1106 ODPH_ERR(
"Error: TCP protocol supported only with copy transmit mode\n");
1110 test_options->eth_type = test_options->num_custom_l3 ?
1111 test_options->custom_l3.eth_type : ODPH_ETHTYPE_IPV4;
1112 test_options->l3_len = test_options->num_custom_l3 ?
1113 test_options->custom_l3.tot_len : ODPH_IPV4HDR_LEN;
1114 test_options->hdr_len = ODPH_ETHHDR_LEN + (test_options->num_vlan * ODPH_VLANHDR_LEN) +
1115 test_options->l3_len;
1117 if (test_options->l4_proto != L4_PROTO_NONE)
1118 test_options->hdr_len += test_options->l4_proto == L4_PROTO_UDP ?
1119 ODPH_UDPHDR_LEN : ODPH_TCPHDR_LEN;
1121 pkt_len = test_options->use_rand_pkt_len ?
1122 test_options->rand_pkt_len_min : test_options->pkt_len;
1124 req_len = test_options->hdr_len;
1125 if (test_options->calc_latency)
1126 req_len +=
sizeof(ts_data_t);
1128 if (test_options->num_custom_l3 && test_options->cs_offload) {
1129 ODPH_ERR(
"Error: Checksum offloading supported only with IP\n");
1134 if (test_options->l4_proto != L4_PROTO_UDP)
1135 test_options->calc_cs = 1;
1137 if (test_options->cs_offload)
1138 test_options->calc_cs = 0;
1140 if (req_len > pkt_len) {
1141 ODPH_ERR(
"Error: Headers do not fit into packet length of %" PRIu32
" bytes "
1142 "(min %" PRIu32
" bytes required)\n", pkt_len, req_len);
1146 if (test_options->lso.enabled) {
1147 if (test_options->tx_mode != TX_MODE_COPY) {
1148 ODPH_ERR(
"Error: LSO supported only with copy transmit mode\n");
1152 if (test_options->num_custom_l3 &&
1154 ODPH_ERR(
"Error: LSO and L3 protocol mismatch\n");
1158 if (test_options->l4_proto != L4_PROTO_TCP &&
1160 ODPH_ERR(
"Error: LSO and L4 protocol mismatch\n");
1167static int set_num_cpu(test_global_t *global)
1170 test_options_t *test_options = &global->test_options;
1171 int num_cpu = test_options->num_cpu;
1175 if (ret != num_cpu) {
1180 ODPH_ERR(
"Error: Too many workers. Maximum supported %i.\n", ret);
1187 if (ret < num_cpu) {
1188 ODPH_ERR(
"Error: Not enough CPUs. Maximum supported %i.\n", ret);
1194 while (ret > num_cpu) {
1210 uint32_t max_segments;
1211 uint32_t pkt_payload;
1212 const uint32_t max_pkt_len = opt->use_rand_pkt_len ?
1213 opt->rand_pkt_len_max : opt->pkt_len;
1217 ODPH_ERR(
"Error (%s): Not enough LSO profiles (max %" PRIu32
")\n", name,
1224 ODPH_ERR(
"Error (%s): ODP_LSO_PROTO_TCP_IPV4 not supported\n", name);
1228 ODPH_ERR(
"Error (%s): ODP_LSO_PROTO_IPV4 not supported\n", name);
1232 ODPH_ERR(
"Error (%s): ODP_LSO_PROTO_CUSTOM not supported\n", name);
1239 ODPH_ERR(
"Error (%s): Allocating test packet failed\n", name);
1247 ODPH_ERR(
"Error (%s): Max LSO packet segments: %" PRIu32
"\n", name,
1253 pkt_payload = max_pkt_len - opt->lso.payload_offset;
1254 max_segments = (pkt_payload + opt->lso.max_payload_len - 1) /
1255 opt->lso.max_payload_len;
1257 ODPH_ERR(
"Error (%s): Max LSO segments: %" PRIu32
"\n", name,
1263 ODPH_ERR(
"Error (%s): Max LSO payload len: %" PRIu32
"\n", name,
1269 ODPH_ERR(
"Error (%s): Max LSO payload offset: %" PRIu32
"\n", name,
1276 ODPH_ERR(
"Error (%s): Max LSO custom fields: %" PRIu32
"\n", name,
1281 for (uint8_t i = 0; i < opt->lso.param.custom.num_custom; i++) {
1284 ODPH_ERR(
"Error (%s): ODP_LSO_ADD_SEGMENT_NUM not supported\n",
1290 ODPH_ERR(
"Error (%s): ODP_LSO_ADD_PAYLOAD_LEN not supported\n",
1296 ODPH_ERR(
"Error (%s): ODP_LSO_ADD_PAYLOAD_OFFSET not supported\n",
1302 ODPH_ERR(
"Error (%s): ODP_LSO_WRITE_BITS not supported\n",
1312static int create_packet_pool(test_global_t *global)
1314 test_options_t *test_options = &global->test_options;
1315 uint32_t num_pkt = test_options->num_pkt;
1316 uint32_t pkt_len = test_options->use_rand_pkt_len ? test_options->rand_pkt_len_max :
1317 test_options->pkt_len;
1325 ODPH_ERR(
"Error: Pool capability failed.\n");
1330 ODPH_ERR(
"Error: Too many packets. Max %u supported.\n", pool_capa.
pkt.
max_num);
1335 ODPH_ERR(
"Error: Too large packets. Max %u supported length.\n",
1340 seg_len = test_options->hdr_len;
1342 ODPH_ERR(
"Error: Max segment length is too small %u\n", pool_capa.
pkt.
max_seg_len);
1348 pool_param.
pkt.
num = num_pkt;
1349 pool_param.
pkt.
len = pkt_len;
1355 ODPH_ERR(
"Error: Pool create failed.\n");
1361static int destroy_packet_pool(test_global_t *global)
1364 ODPH_ERR(
"Error: Pool destroy failed.\n");
1370static int open_pktios(test_global_t *global)
1381 test_options_t *test_options = &global->test_options;
1382 int num_rx = test_options->num_rx;
1383 int num_tx = test_options->num_tx;
1384 uint32_t num_pktio = test_options->num_pktio;
1385 uint32_t num_pkt = test_options->num_pkt;
1386 uint32_t pkt_len = test_options->use_rand_pkt_len ?
1387 test_options->rand_pkt_len_max : test_options->pkt_len;
1389 printf(
"\nODP packet generator\n");
1390 printf(
" quit test after: %" PRIu64
" rounds\n",
1391 test_options->quit);
1392 printf(
" num rx threads: %i\n", num_rx);
1393 printf(
" num tx threads: %i\n", num_tx);
1394 printf(
" num packets: %u\n", num_pkt);
1395 if (test_options->use_rand_pkt_len)
1396 printf(
" packet length: %u-%u bytes, %u bins\n",
1397 test_options->rand_pkt_len_min,
1398 test_options->rand_pkt_len_max,
1399 test_options->rand_pkt_len_bins);
1401 printf(
" packet length: %u bytes\n", pkt_len);
1403 if (test_options->mtu)
1404 printf(
"%u bytes\n", test_options->mtu);
1406 printf(
"interface default\n");
1407 printf(
" packet input mode: %s\n", test_options->direct_rx ?
"direct" :
"scheduler");
1408 printf(
" promisc mode: %s\n", test_options->promisc_mode ?
"enabled" :
"disabled");
1409 printf(
" transmit mode: %i\n", test_options->tx_mode);
1410 printf(
" measure latency: %s\n", test_options->calc_latency ?
"enabled" :
"disabled");
1411 printf(
" UDP SW checksum: %s\n", test_options->calc_cs ?
"enabled" :
"disabled");
1412 printf(
" Checksum offload: %s\n", test_options->cs_offload ?
"enabled" :
"disabled");
1413 printf(
" payload filling: %s\n", test_options->fill_pl ?
"enabled" :
"disabled");
1414 printf(
" tx burst size: %u\n", test_options->burst_size);
1415 printf(
" tx bursts: %u\n", test_options->bursts);
1416 printf(
" tx burst gap: %" PRIu64
" nsec\n",
1417 test_options->gap_nsec);
1419 if (test_options->lso.enabled) {
1420 printf(
" LSO protocol: %s\n",
1422 "ODP_LSO_PROTO_IPV4" :
1424 "ODP_LSO_PROTO_TCP_IPV4" :
"ODP_LSO_PROTO_CUSTOM");
1425 printf(
" max payload offset: %" PRIu32
" bytes\n",
1426 test_options->lso.payload_offset);
1427 printf(
" max payload len: %" PRIu32
" bytes\n",
1428 test_options->lso.max_payload_len);
1430 for (i = 0; i < test_options->lso.param.custom.num_custom; i++) {
1432 test_options->lso.param.custom.field[i].mod_op;
1433 const char *mod_op_str;
1437 mod_op_str =
"ODP_LSO_ADD_SEGMENT_NUM";
1440 mod_op_str =
"ODP_LSO_ADD_PAYLOAD_LEN";
1443 mod_op_str =
"ODP_LSO_ADD_PAYLOAD_OFFSET";
1446 mod_op_str =
"ODP_LSO_WRITE_BITS";
1449 mod_op_str =
"UNKNOWN";
1453 printf(
" Custom operation %" PRIu32
": %s\n", i + 1, mod_op_str);
1454 printf(
" offset: %" PRIu32
" bytes\n",
1455 test_options->lso.param.custom.field[i].offset);
1456 printf(
" size: %" PRIu32
" bytes\n",
1457 test_options->lso.param.custom.field[i].size);
1461 &test_options->lso.param.custom.field[i].write_bits.first_seg;
1463 &test_options->lso.param.custom.field[i].write_bits.middle_seg;
1465 &test_options->lso.param.custom.field[i].write_bits.last_seg;
1467 printf(
" first seg: 0x%02x/0x%02x\n",
1469 printf(
" middle seg: 0x%02x/0x%02x\n",
1471 printf(
" last seg: 0x%02x/0x%02x\n",
1478 for (i = 0; i < test_options->num_vlan; i++) {
1479 printf(
" VLAN[%i]: %x:%x\n", i,
1480 test_options->vlan[i].tpid, test_options->vlan[i].tci);
1483 printf(
" L3 protocol: ");
1485 if (test_options->num_custom_l3) {
1488 " total length: %u\n"
1489 " fields:\n", test_options->custom_l3.eth_type,
1490 test_options->custom_l3.tot_len);
1492 for (i = 0; i < test_options->num_custom_l3; i++) {
1493 printf(
" name: %s\n"
1495 " value: %" PRIx64
"\n"
1496 " diff: %" PRIi64
"\n\n",
1497 test_options->custom_l3.fields[i].name,
1498 test_options->custom_l3.fields[i].len,
1499 test_options->custom_l3.fields[i].value,
1500 test_options->custom_l3.fields[i].diff);
1504 printf(
" IPv4 source: %s\n", test_options->ipv4_src_s);
1505 printf(
" IPv4 destination: %s\n\n", test_options->ipv4_dst_s);
1508 printf(
" L4 protocol: %s\n",
1509 test_options->l4_proto == L4_PROTO_UDP ?
1510 "UDP" : test_options->l4_proto == L4_PROTO_TCP ?
"TCP" :
"none");
1511 printf(
" source port: %u\n", test_options->src_port);
1512 printf(
" destination port: %u\n", test_options->dst_port);
1513 printf(
" src port count: %u\n", test_options->c_mode.src_port);
1514 printf(
" dst port count: %u\n", test_options->c_mode.dst_port);
1515 printf(
" num pktio: %u\n", num_pktio);
1517 printf(
" interfaces names: ");
1518 for (i = 0; i < num_pktio; i++) {
1521 printf(
"%s\n", test_options->pktio_name[i]);
1524 printf(
" destination MACs: ");
1525 for (i = 0; i < num_pktio; i++) {
1526 uint8_t *eth_dst = global->pktio[i].eth_dst.addr;
1530 printf(
"%02x:%02x:%02x:%02x:%02x:%02x\n",
1531 eth_dst[0], eth_dst[1], eth_dst[2],
1532 eth_dst[3], eth_dst[4], eth_dst[5]);
1538 pktio_param.
in_mode = num_rx ? (test_options->direct_rx ?
1544 for (i = 0; i < num_pktio; i++) {
1550 for (i = 0; i < num_pktio; i++) {
1551 name = test_options->pktio_name[i];
1555 ODPH_ERR(
"Error (%s): Pktio open failed.\n", name);
1559 global->pktio[i].pktio = pktio;
1564 if (pktio_idx < 0) {
1565 ODPH_ERR(
"Error (%s): Reading pktio index failed: %i\n", name, pktio_idx);
1568 global->if_from_pktio_idx[pktio_idx] = i;
1571 ODPH_ERR(
"Error (%s): Pktio capability failed.\n", name);
1576 ODPH_ERR(
"Error (%s): Too many RX threads. Interface supports max %u input queues.\n",
1582 ODPH_ERR(
"Error (%s): Too many TX threads. Interface supports max %u output queues.\n",
1588 &global->pktio[i].eth_src.addr,
1589 ODPH_ETHADDR_LEN) != ODPH_ETHADDR_LEN) {
1590 ODPH_ERR(
"Error (%s): MAC address read failed.\n", name);
1594 if (test_options->mtu) {
1595 uint32_t maxlen_input = pktio_capa.
maxlen.
max_input ? test_options->mtu : 0;
1597 test_options->mtu : 0;
1600 ODPH_ERR(
"Error (%s): modifying interface MTU not supported.\n",
1608 ODPH_ERR(
"Error (%s): unsupported MTU value %" PRIu32
" "
1609 "(min %" PRIu32
", max %" PRIu32
")\n", name, maxlen_input,
1613 if (maxlen_output &&
1616 ODPH_ERR(
"Error (%s): unsupported MTU value %" PRIu32
" "
1617 "(min %" PRIu32
", max %" PRIu32
")\n", name,
1624 ODPH_ERR(
"Error (%s): setting MTU failed\n", name);
1630 ODPH_ERR(
"Error (%s): Don't free mode not supported\n", name);
1634 ODPH_ERR(
"Error (%s): Static-reference TX mode not supported\n", name);
1640 if (test_options->cs_offload) {
1641 if (test_options->l4_proto == L4_PROTO_UDP) {
1647 ODPH_ERR(
"Warning (%s): UDP checksum offload at RX not "
1648 "properly supported, leaving it disabled.\n",
1653 ODPH_ERR(
"Error (%s): UDP checksum offload at TX not "
1654 "properly supported.\n", name);
1662 if (test_options->l4_proto == L4_PROTO_TCP) {
1668 ODPH_ERR(
"Warning (%s): TCP checksum offload at RX not "
1669 "properly supported, leaving it disabled.\n",
1674 ODPH_ERR(
"Error (%s): TCP checksum offload at TX not "
1675 "properly supported.\n", name);
1686 if (test_options->lso.enabled) {
1687 if (check_lso_capa(name, &pktio_capa, test_options, global->pool))
1694 ODPH_ERR(
"Error (%s): Pktio config failed.\n", name);
1698 if (test_options->lso.enabled) {
1703 ODPH_ERR(
"Error (%s): LSO profile create failed.\n", name);
1710 ODPH_ERR(
"Error (%s): promisc mode set not supported\n", name);
1715 ODPH_ERR(
"Error (%s): promisc mode enable failed\n", name);
1722 if (test_options->direct_rx) {
1738 ODPH_ERR(
"Error (%s): Pktin config failed.\n", name);
1747 ODPH_ERR(
"Error (%s): Pktout config failed.\n", name);
1755 ODPH_ERR(
"Error (%s): Pktout queue request failed.\n", name);
1759 for (j = 0; j < num_tx; j++)
1760 global->pktio[i].pktout[j] = pktout[j];
1763 if (num_rx > 0 && test_options->direct_rx) {
1767 ODPH_ERR(
"Error (%s): Pktin queue request failed.\n", name);
1771 for (j = 0; j < num_rx; j++)
1772 global->pktio[i].pktin[j] = pktin[j];
1779static int start_pktios(test_global_t *global)
1782 test_options_t *test_options = &global->test_options;
1783 uint32_t num_pktio = test_options->num_pktio;
1785 const char *names[MAX_PKTIOS];
1787 for (i = 0; i < num_pktio; i++) {
1789 ODPH_ERR(
"Error (%s): Pktio start failed.\n", test_options->pktio_name[i]);
1794 global->pktio[i].started = 1;
1795 pktios[i] = global->pktio[i].pktio;
1796 names[i] = test_options->pktio_name[i];
1800 if (test_options->wait_sec &&
1801 pktio_common_check_link_status_wait(pktios, names, num_pktio,
1802 test_options->wait_sec) == -1)
1805 pktio_common_print_link_info_multi(pktios, names, num_pktio);
1807 if (test_options->wait_start_sec)
1813static int stop_pktios(test_global_t *global)
1818 test_options_t *test_options = &global->test_options;
1819 uint32_t num_pktio = test_options->num_pktio;
1821 for (i = 0; i < num_pktio; i++) {
1822 pktio = global->pktio[i].pktio;
1828 ODPH_ERR(
"Error (%s): Pktio stop failed.\n", test_options->pktio_name[i]);
1836static int close_pktios(test_global_t *global)
1840 test_options_t *test_options = &global->test_options;
1841 uint32_t num_pktio = test_options->num_pktio;
1844 for (i = 0; i < num_pktio; i++) {
1845 pktio = global->pktio[i].pktio;
1852 ODPH_ERR(
"Error (%s): LSO profile destroy failed.\n",
1853 test_options->pktio_name[i]);
1858 ODPH_ERR(
"Error (%s): Pktio close failed.\n", test_options->pktio_name[i]);
1866static inline void get_timestamp(
odp_packet_t pkt, uint32_t ts_off, rx_lat_data_t *lat_data,
1873 ts_data.magic != TS_MAGIC))
1878 if (nsec < lat_data->min)
1879 lat_data->min = nsec;
1881 if (nsec > lat_data->max)
1882 lat_data->max = nsec;
1884 lat_data->nsec += nsec;
1885 lat_data->packets++;
1888static int rx_thread(
void *arg)
1894 thread_arg_t *thread_arg = arg;
1895 test_global_t *global = thread_arg->global;
1896 int direct_rx = global->test_options.direct_rx;
1897 int periodic_stat = global->test_options.update_msec ? 1 : 0;
1898 uint64_t rx_timeouts = 0;
1899 uint64_t rx_packets = 0;
1900 uint64_t rx_bytes = 0;
1903 int clock_started = 0;
1904 int exit_timer_started = 0;
1906 const int max_num = 32;
1908 int num_pktio = global->test_options.num_pktio;
1911 uint32_t ts_off = global->test_options.calc_latency ? global->test_options.hdr_len : 0;
1913 rx_lat_data_t rx_lat_data = { .
nsec = 0, .min = UINT64_MAX, .max = 0, .packets = 0 };
1916 global->stat[thr].thread_type = RX_THREAD;
1919 for (i = 0; i < num_pktio; i++)
1920 pktin_queue[i] = thread_arg->pktin[i];
1931 ODPH_ERR(
"pktin (%i) recv failed: %i\n", pktin, num);
1938 if (pktin >= num_pktio)
1955 if (exit_timer_started == 0) {
1958 exit_timer_started = 1;
1961 if (direct_rx == 0 && paused == 0) {
1964 }
else if (num == 0) {
1985 if (!clock_started) {
1991 for (i = 0; i < num; i++) {
1995 get_timestamp(pkt[i], ts_off, &rx_lat_data, rx_ts);
2006 int if_idx = global->if_from_pktio_idx[index];
2008 global->stat[thr].pktio[if_idx].rx_packets += num;
2019 global->stat[thr].time_nsec = nsec;
2020 global->stat[thr].rx_timeouts = rx_timeouts;
2021 global->stat[thr].rx_packets = rx_packets;
2022 global->stat[thr].rx_bytes = rx_bytes;
2023 global->stat[thr].rx_lat_nsec = rx_lat_data.nsec;
2024 global->stat[thr].rx_lat_min_nsec = rx_lat_data.min;
2025 global->stat[thr].rx_lat_max_nsec = rx_lat_data.max;
2026 global->stat[thr].rx_lat_packets = rx_lat_data.packets;
2031static void drain_scheduler(test_global_t *global)
2036 if (!global->test_options.num_rx)
2047static void drain_direct_input(test_global_t *global)
2052 int num_pktio = global->test_options.num_pktio;
2053 int num_rx = global->test_options.num_rx;
2055 for (i = 0; i < num_pktio; i++) {
2056 for (j = 0; j < num_rx; j++) {
2057 pktin = global->pktio[i].pktin[j];
2067static inline uint8_t *copy_field(uint8_t *dst, uint8_t *src, uint32_t len)
2069 return (uint8_t *)memcpy(dst, src, len) + len;
2072static int init_packets(test_global_t *global,
int pktio,
2076 uint32_t i, j, pkt_len, seg_len, payload_len, l2_len;
2082 test_options_t *test_options = &global->test_options;
2083 const int proto = test_options->l4_proto;
2084 uint32_t num_vlan = test_options->num_vlan;
2085 uint32_t num_custom_l3 = test_options->num_custom_l3;
2086 uint32_t hdr_len = test_options->hdr_len;
2087 uint16_t src_port = test_options->src_port;
2088 uint16_t dst_port = test_options->dst_port;
2089 uint32_t src_cnt = 0;
2090 uint32_t dst_cnt = 0;
2091 uint32_t tcp_seqnum = 0x1234;
2093 odph_vlanhdr_t *vlan = NULL;
2094 hdr_field_t *c_hdr = NULL;
2096 if (num_vlan > MAX_VLANS)
2097 num_vlan = MAX_VLANS;
2099 for (i = 0; i < num; i++) {
2104 payload_len = pkt_len - hdr_len;
2106 if (seg_len < hdr_len) {
2107 ODPH_ERR(
"Error: First segment too short %u\n", seg_len);
2113 memcpy(eth->dst.addr, global->pktio[pktio].eth_dst.addr, 6);
2114 memcpy(eth->src.addr, global->pktio[pktio].eth_src.addr, 6);
2116 l2_len = ODPH_ETHHDR_LEN;
2121 tpid = test_options->vlan[0].tpid;
2124 if (tpid == ETH_TYPE_QINQ)
2130 for (j = 0; j < num_vlan; j++) {
2131 vlan = (odph_vlanhdr_t *)((uint8_t *)data + l2_len);
2133 if (j < num_vlan - 1) {
2134 tpid = test_options->vlan[j + 1].tpid;
2138 l2_len += ODPH_VLANHDR_LEN;
2147 if (num_custom_l3) {
2149 u8 = (uint8_t *)data + l2_len;
2151 for (j = 0; j < num_custom_l3; j++) {
2152 c_hdr = &test_options->custom_l3.fields[j];
2153 value = bswap(c_hdr->value, c_hdr->len);
2154 u8 = copy_field(u8, (uint8_t *)&value, c_hdr->len);
2155 c_hdr->value += c_hdr->diff;
2159 ip = (odph_ipv4hdr_t *)((uint8_t *)data + l2_len);
2160 memset(ip, 0, ODPH_IPV4HDR_LEN);
2161 ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN;
2166 ip->proto = proto == L4_PROTO_UDP ?
2167 ODPH_IPPROTO_UDP : proto == L4_PROTO_TCP ?
2168 ODPH_IPPROTO_TCP : 0xFE;
2171 ip->chksum = ~odp_chksum_ones_comp16(ip, ODPH_IPV4HDR_LEN);
2174 u8 = ((uint8_t *)data + l2_len + ODPH_IPV4HDR_LEN);
2179 if (proto == L4_PROTO_TCP) {
2180 odph_tcphdr_t *tcp = (odph_tcphdr_t *)u8;
2182 memset(tcp, 0, ODPH_TCPHDR_LEN);
2190 tcp_seqnum += payload_len;
2192 }
else if (proto == L4_PROTO_UDP) {
2193 odph_udphdr_t *udp = (odph_udphdr_t *)u8;
2195 memset(udp, 0, ODPH_UDPHDR_LEN);
2206 if (test_options->fill_pl) {
2208 for (j = 0; j < seg_len - hdr_len; j++)
2213 if (proto == L4_PROTO_UDP && !test_options->calc_latency && test_options->calc_cs)
2214 odph_udp_chksum_set(pkt);
2217 if (test_options->c_mode.src_port) {
2219 if (src_cnt < test_options->c_mode.src_port) {
2222 src_port = test_options->src_port;
2226 if (test_options->c_mode.dst_port) {
2228 if (dst_cnt < test_options->c_mode.dst_port) {
2231 dst_port = test_options->dst_port;
2250 tcp_base->seq_no = tcp->seq_no;
2253 odph_tcp_chksum_set(pkt);
2256static inline int update_rand_data(uint8_t *data, uint32_t data_len)
2258 uint32_t generated = 0;
2259 uint32_t retries = 0;
2261 while (generated < data_len) {
2265 ODPH_ERR(
"Error: odp_random_data() failed: %" PRId32
"\n", ret);
2270 ODPH_ERR(
"Error: Failed to create random data\n");
2281static int init_global_data(test_global_t *global)
2283 memset(global, 0,
sizeof(test_global_t));
2286 for (
int i = 0; i < MAX_THREADS; i++) {
2287 uint8_t *rand_data = (uint8_t *)global->rand_data[i];
2289 if (
odp_unlikely(update_rand_data(rand_data, RAND_16BIT_WORDS * 2)))
2292 global->thread_arg[i].global = global;
2297static inline void set_timestamp(
odp_packet_t pkt, uint32_t ts_off)
2305 test_global_t *global)
2307 uint32_t i, pkt_len;
2308 test_options_t *test_options = &global->test_options;
2309 uint32_t num_bins = global->num_bins;
2311 pkt_len = test_options->pkt_len;
2313 for (i = 0; i < num; i++) {
2315 pkt_len = global->len_bin[i % num_bins];
2319 ODPH_ERR(
"Error: Alloc of %uB packet failed\n", pkt_len);
2335static inline uint32_t form_burst(
odp_packet_t out_pkt[], uint32_t burst_size, uint32_t num_bins,
2337 int tx_mode,
odp_bool_t calc_latency, uint32_t hdr_len,
2338 odp_bool_t calc_cs, uint64_t *total_bytes, uint8_t l4_proto,
2339 const uint16_t *rand_data)
2343 static __thread
int rand_idx;
2346 idx = burst * burst_size;
2348 idx = burst * burst_size * num_bins;
2350 for (i = 0; i < burst_size; i++) {
2358 bin = rand_data[rand_idx++] % num_bins;
2359 pkt = pkt_tbl[idx + bin];
2366 if (tx_mode == TX_MODE_DF) {
2368 }
else if (tx_mode == TX_MODE_REF) {
2380 set_timestamp(out_pkt[i], hdr_len);
2382 if (l4_proto == L4_PROTO_TCP)
2383 update_tcp_hdr(out_pkt[i], pkt, hdr_len, calc_cs);
2384 else if (l4_proto == L4_PROTO_UDP && calc_latency && calc_cs)
2385 odph_udp_chksum_set(out_pkt[i]);
2391 *total_bytes = bytes;
2397 uint32_t num,
int tx_mode, uint64_t *drop_bytes,
2412 uint32_t num_drop = num - sent;
2414 for (i = sent; i < num; i++)
2417 if (tx_mode != TX_MODE_DF)
2421 *drop_bytes = bytes;
2427 int tx_mode
ODP_UNUSED, uint64_t *drop_bytes,
2442 uint32_t num_drop = num - sent;
2444 for (i = sent; i < num; i++)
2450 *drop_bytes = bytes;
2455static int tx_thread(
void *arg)
2458 uint32_t exit_test, num_alloc, j;
2460 uint64_t diff_ns, t1_nsec;
2462 thread_arg_t *thread_arg = arg;
2463 test_global_t *global = thread_arg->global;
2464 test_options_t *test_options = &global->test_options;
2465 int periodic_stat = test_options->update_msec ? 1 : 0;
2467 uint64_t gap_nsec = test_options->gap_nsec;
2468 uint64_t quit = test_options->quit;
2469 uint64_t tx_timeouts = 0;
2470 uint64_t tx_bytes = 0;
2471 uint64_t tx_packets = 0;
2472 uint64_t tx_drops = 0;
2475 const uint32_t hdr_len = test_options->hdr_len;
2476 const uint32_t burst_size = test_options->burst_size;
2477 const uint32_t bursts = test_options->bursts;
2478 const uint32_t num_tx = test_options->num_tx;
2479 const uint16_t *rand_data = global->rand_data[thr];
2480 const uint8_t l4_proto = test_options->l4_proto;
2481 const int tx_mode = test_options->tx_mode;
2482 const odp_bool_t calc_cs = test_options->calc_cs;
2483 const odp_bool_t calc_latency = test_options->calc_latency;
2484 int num_pktio = test_options->num_pktio;
2487 uint32_t tot_packets = 0;
2488 uint32_t num_bins = global->num_bins;
2489 const send_fn_t send_burst_fn = test_options->lso.enabled ? send_burst_lso : send_burst;
2491 tx_thr = thread_arg->tx_thr;
2492 global->stat[thr].thread_type = TX_THREAD;
2494 num_alloc = global->num_tx_pkt;
2496 num_alloc = global->num_tx_pkt * num_bins;
2498 for (i = 0; i < num_pktio; i++) {
2499 int seq = i * num_alloc;
2501 pktout[i] = thread_arg->pktout[i];
2502 pkt_tbl = thread_arg->packet[i];
2504 lso_opt[i].
lso_profile = thread_arg->lso_profile[i];
2508 if (alloc_packets(pool, pkt_tbl, num_alloc, global)) {
2513 tot_packets += num_alloc;
2515 if (init_packets(global, i, pkt_tbl, num_alloc, seq)) {
2520 if (tx_mode == TX_MODE_DF) {
2521 for (j = 0; j < num_alloc; j++)
2533 t1_nsec =
odp_time_to_ns(t1) + gap_nsec + (tx_thr * gap_nsec / num_tx);
2540 if (quit && tx_timeouts >= quit) {
2546 uint64_t nsec = t1_nsec + tx_timeouts * gap_nsec;
2554 for (i = 0; i < num_pktio; i++) {
2557 uint64_t total_bytes, drop_bytes;
2560 pkt_tbl = thread_arg->packet[i];
2562 for (j = 0; j < bursts; j++) {
2563 num = form_burst(pkt, burst_size, num_bins, j, pkt_tbl, pool,
2564 tx_mode, calc_latency, hdr_len, calc_cs,
2565 &total_bytes, l4_proto, rand_data);
2568 tx_drops += burst_size;
2572 sent = send_burst_fn(pktout[i], pkt, num, tx_mode, &drop_bytes,
2577 tx_drops += burst_size;
2581 tx_bytes += total_bytes - drop_bytes;
2584 tx_drops += burst_size - sent;
2587 global->stat[thr].pktio[i].tx_packets += sent;
2595 for (i = 0; i < num_pktio; i++) {
2596 pkt_tbl = thread_arg->packet[i];
2598 if (tot_packets == 0)
2602 tot_packets -= num_alloc;
2606 global->stat[thr].time_nsec = diff_ns;
2607 global->stat[thr].tx_timeouts = tx_timeouts;
2608 global->stat[thr].tx_bytes = tx_bytes;
2609 global->stat[thr].tx_packets = tx_packets;
2610 global->stat[thr].tx_drops = tx_drops;
2615static int start_workers(test_global_t *global,
odp_instance_t instance)
2617 odph_thread_common_param_t thr_common;
2618 int i, j, ret, tx_thr;
2619 test_options_t *test_options = &global->test_options;
2620 int num_pktio = test_options->num_pktio;
2621 int num_rx = test_options->num_rx;
2622 int num_cpu = test_options->num_cpu;
2623 odph_thread_param_t thr_param[num_cpu];
2625 memset(global->thread_tbl, 0,
sizeof(global->thread_tbl));
2626 odph_thread_common_param_init(&thr_common);
2628 thr_common.instance = instance;
2629 thr_common.cpumask = &global->cpumask;
2632 for (i = 0; i < num_rx; i++) {
2634 for (j = 0; test_options->direct_rx && j < num_pktio; j++)
2635 global->thread_arg[i].pktin[j] = global->pktio[j].pktin[i];
2637 odph_thread_param_init(&thr_param[i]);
2638 thr_param[i].start = rx_thread;
2639 thr_param[i].arg = &global->thread_arg[i];
2645 for (i = num_rx; i < num_cpu; i++) {
2646 for (j = 0; j < num_pktio; j++) {
2649 global->thread_arg[i].tx_thr = tx_thr;
2653 pktout = global->pktio[j].pktout[tx_thr];
2654 global->thread_arg[i].pktout[j] = pktout;
2656 global->thread_arg[i].lso_profile[j] = global->pktio[j].lso_profile;
2659 odph_thread_param_init(&thr_param[i]);
2660 thr_param[i].start = tx_thread;
2661 thr_param[i].arg = &global->thread_arg[i];
2666 ret = odph_thread_create(global->thread_tbl, &thr_common, thr_param,
2669 if (ret != num_cpu) {
2670 ODPH_ERR(
"Error: thread create failed %i\n", ret);
2677static void print_periodic_stat(test_global_t *global, uint64_t nsec)
2680 int num_pktio = global->test_options.num_pktio;
2681 double sec = nsec / 1000000000.0;
2682 uint64_t num_tx[num_pktio];
2683 uint64_t num_rx[num_pktio];
2685 for (i = 0; i < num_pktio; i++) {
2689 for (j = 0; j < MAX_THREADS; j++) {
2690 if (global->stat[j].thread_type == RX_THREAD)
2691 num_rx[i] += global->stat[j].pktio[i].rx_packets;
2692 else if (global->stat[j].thread_type == TX_THREAD)
2693 num_tx[i] += global->stat[j].pktio[i].tx_packets;
2696 if (global->test_options.num_tx) {
2697 printf(
" TX: %12.6fs", sec);
2698 for (i = 0; i < num_pktio; i++)
2699 printf(
" %10" PRIu64
"", num_tx[i]);
2703 if (global->test_options.num_rx) {
2704 printf(
" RX: %12.6fs", sec);
2705 for (i = 0; i < num_pktio; i++)
2706 printf(
" %10" PRIu64
"", num_rx[i]);
2711static void periodic_print_loop(test_global_t *global)
2716 int num_pktio = global->test_options.num_pktio;
2718 printf(
"\n\nPackets per interface\n");
2719 printf(
" Dir Time");
2720 for (i = 0; i < num_pktio; i++)
2723 printf(
"\n -----------------");
2724 for (i = 0; i < num_pktio; i++)
2725 printf(
"-----------");
2731 usleep(1000 * global->test_options.update_msec);
2734 print_periodic_stat(global, nsec);
2738static void print_humanised_time(
double time_nsec)
2747 printf(
"%.0f ns\n", time_nsec);
2750static void print_humanised_latency(
double lat_nsec,
double lat_min_nsec,
double lat_max_nsec)
2752 printf(
" rx ave packet latency: ");
2753 print_humanised_time(lat_nsec);
2754 printf(
" rx min packet latency: ");
2755 print_humanised_time(lat_min_nsec);
2756 printf(
" rx max packet latency: ");
2757 print_humanised_time(lat_max_nsec);
2760static int print_final_stat(test_global_t *global)
2763 double rx_mbit_per_sec, tx_mbit_per_sec;
2764 test_options_t *test_options = &global->test_options;
2765 int num_rx = test_options->num_rx;
2766 int num_tx = test_options->num_tx;
2767 uint64_t rx_nsec_sum = 0;
2768 uint64_t rx_pkt_sum = 0;
2769 uint64_t rx_byte_sum = 0;
2770 uint64_t rx_tmo_sum = 0;
2771 uint64_t rx_lat_nsec_sum = 0;
2772 uint64_t rx_lat_min_nsec = UINT64_MAX;
2773 uint64_t rx_lat_max_nsec = 0;
2774 uint64_t rx_lat_pkt_sum = 0;
2775 uint64_t tx_nsec_sum = 0;
2776 uint64_t tx_pkt_sum = 0;
2777 uint64_t tx_byte_sum = 0;
2778 uint64_t tx_drop_sum = 0;
2779 uint64_t tx_tmo_sum = 0;
2780 double rx_pkt_ave = 0.0;
2781 double rx_pkt_per_sec = 0.0;
2782 double rx_byte_per_sec = 0.0;
2783 double rx_pkt_len = 0.0;
2784 double rx_sec = 0.0;
2785 double rx_ave_lat_nsec = 0.0;
2786 double tx_pkt_per_sec = 0.0;
2787 double tx_byte_per_sec = 0.0;
2788 double tx_sec = 0.0;
2790 printf(
"\nRESULTS PER THREAD\n");
2791 printf(
" rx thread:\n");
2792 printf(
" 1 2 3 4 5 6 7 8\n");
2793 printf(
" ---------------------------------------------------------------------------------------\n");
2797 for (i = 0; i < MAX_THREADS; i++) {
2798 if (global->stat[i].thread_type != RX_THREAD)
2801 if (num_thr && (num_thr % 8) == 0)
2804 printf(
"%10" PRIu64
" ", global->stat[i].rx_packets);
2810 printf(
" tx thread:\n");
2811 printf(
" 1 2 3 4 5 6 7 8\n");
2812 printf(
" ---------------------------------------------------------------------------------------\n");
2816 for (i = 0; i < MAX_THREADS; i++) {
2817 if (global->stat[i].thread_type != TX_THREAD)
2820 if (num_thr && (num_thr % 8) == 0)
2823 printf(
"%10" PRIu64
" ", global->stat[i].tx_packets);
2829 for (i = 0; i < MAX_THREADS; i++) {
2830 if (global->stat[i].thread_type == RX_THREAD) {
2831 rx_tmo_sum += global->stat[i].rx_timeouts;
2832 rx_pkt_sum += global->stat[i].rx_packets;
2833 rx_byte_sum += global->stat[i].rx_bytes;
2834 rx_nsec_sum += global->stat[i].time_nsec;
2835 rx_lat_nsec_sum += global->stat[i].rx_lat_nsec;
2836 rx_lat_pkt_sum += global->stat[i].rx_lat_packets;
2838 if (global->stat[i].rx_lat_min_nsec < rx_lat_min_nsec)
2839 rx_lat_min_nsec = global->stat[i].rx_lat_min_nsec;
2841 if (global->stat[i].rx_lat_max_nsec > rx_lat_max_nsec)
2842 rx_lat_max_nsec = global->stat[i].rx_lat_max_nsec;
2843 }
else if (global->stat[i].thread_type == TX_THREAD) {
2844 tx_tmo_sum += global->stat[i].tx_timeouts;
2845 tx_pkt_sum += global->stat[i].tx_packets;
2846 tx_byte_sum += global->stat[i].tx_bytes;
2847 tx_drop_sum += global->stat[i].tx_drops;
2848 tx_nsec_sum += global->stat[i].time_nsec;
2853 rx_pkt_ave = (double)rx_pkt_sum / num_rx;
2854 rx_sec = rx_nsec_sum / 1000000000.0;
2855 tx_sec = tx_nsec_sum / 1000000000.0;
2859 rx_pkt_per_sec = (1000000000.0 * (double)rx_pkt_sum) /
2860 (double)rx_nsec_sum;
2862 rx_byte_per_sec = 1000000000.0;
2863 rx_byte_per_sec *= (rx_byte_sum + 24 * rx_pkt_sum);
2864 rx_byte_per_sec /= (double)rx_nsec_sum;
2868 tx_pkt_per_sec = (1000000000.0 * (double)tx_pkt_sum) /
2869 (double)tx_nsec_sum;
2871 tx_byte_per_sec = 1000000000.0;
2872 tx_byte_per_sec *= (tx_byte_sum + 24 * tx_pkt_sum);
2873 tx_byte_per_sec /= (double)tx_nsec_sum;
2877 rx_mbit_per_sec = (num_rx * 8 * rx_byte_per_sec) / 1000000.0;
2878 tx_mbit_per_sec = (num_tx * 8 * tx_byte_per_sec) / 1000000.0;
2881 rx_pkt_len = (double)rx_byte_sum / rx_pkt_sum;
2884 rx_ave_lat_nsec = (double)rx_lat_nsec_sum / rx_lat_pkt_sum;
2886 printf(
"TOTAL (%i rx and %i tx threads)\n", num_rx, num_tx);
2887 printf(
" rx timeouts: %" PRIu64
"\n", rx_tmo_sum);
2888 printf(
" rx time spent (sec): %.3f\n", rx_sec);
2889 printf(
" rx packets: %" PRIu64
"\n", rx_pkt_sum);
2890 printf(
" rx packets drained: %" PRIu64
"\n", global->drained);
2891 printf(
" rx packets per thr: %.1f\n", rx_pkt_ave);
2892 printf(
" rx packets per thr per sec: %.1f\n", rx_pkt_per_sec);
2893 printf(
" rx packets per sec: %.1f\n", num_rx * rx_pkt_per_sec);
2894 printf(
" rx ave packet len: %.1f\n", rx_pkt_len);
2897 print_humanised_latency(rx_ave_lat_nsec, rx_lat_min_nsec, rx_lat_max_nsec);
2899 printf(
" rx Mbit/s: %.1f\n", rx_mbit_per_sec);
2901 printf(
" tx timeouts: %" PRIu64
"\n", tx_tmo_sum);
2902 printf(
" tx time spent (sec): %.3f\n", tx_sec);
2903 printf(
" tx packets: %" PRIu64
"\n", tx_pkt_sum);
2904 printf(
" tx dropped packets: %" PRIu64
"\n", tx_drop_sum);
2905 printf(
" tx packets per thr per sec: %.1f\n", tx_pkt_per_sec);
2906 printf(
" tx packets per sec: %.1f\n", num_tx * tx_pkt_per_sec);
2907 printf(
" tx Mbit/s: %.1f\n", tx_mbit_per_sec);
2910 if (rx_pkt_sum < MIN_RX_PACKETS_CI)
2916static void sig_handler(
int signo)
2920 if (test_global == NULL)
2926int main(
int argc,
char **argv)
2928 odph_helper_options_t helper_options;
2931 test_global_t *global;
2935 signal(SIGINT, sig_handler);
2938 argc = odph_parse_options(argc, argv);
2939 if (odph_options(&helper_options)) {
2940 ODPH_ERR(
"Error: reading ODP helper options failed.\n");
2953 init.
mem_model = helper_options.mem_model;
2957 ODPH_ERR(
"Error: Global init failed.\n");
2963 ODPH_ERR(
"Error: Local init failed.\n");
2968 ODP_CACHE_LINE_SIZE, 0);
2971 ODPH_ERR(
"Error: SHM reserve failed.\n");
2976 test_global = global;
2978 if (init_global_data(global)) {
2983 if (parse_options(argc, argv, global)) {
2991 if (global->test_options.direct_rx == 0)
2994 if (set_num_cpu(global)) {
2999 if (create_packet_pool(global)) {
3004 if (open_pktios(global)) {
3009 if (start_pktios(global)) {
3015 start_workers(global, instance);
3021 if (global->test_options.update_msec)
3022 periodic_print_loop(global);
3025 odph_thread_join(global->thread_tbl,
3026 global->test_options.num_cpu);
3028 if (stop_pktios(global))
3031 if (global->test_options.direct_rx)
3032 drain_direct_input(global);
3034 drain_scheduler(global);
3036 if (close_pktios(global))
3039 if (print_final_stat(global))
3043 if (destroy_packet_pool(global)) {
3044 ODPH_ERR(
"Error: destroy_packet_pool() failed.\n");
3049 ODPH_ERR(
"Error: SHM free failed.\n");
3054 ODPH_ERR(
"Error: term local failed.\n");
3059 ODPH_ERR(
"Error: term global failed.\n");
void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val)
Initialize atomic uint32 variable.
void odp_atomic_add_u32(odp_atomic_u32_t *atom, uint32_t val)
Add to atomic uint32 variable.
uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom)
Load value of atomic uint32 variable.
void odp_atomic_inc_u32(odp_atomic_u32_t *atom)
Increment atomic uint32 variable.
void odp_barrier_init(odp_barrier_t *barr, int count)
Initialize barrier with thread count.
void odp_barrier_wait(odp_barrier_t *barr)
Synchronize thread execution on barrier.
#define ODP_PACKED
Defines type/struct to be packed.
#define ODP_ALIGNED_CACHE
Defines type/struct/variable to be cache line size aligned.
#define odp_unlikely(x)
Branch unlikely taken.
odp_u16be_t odp_cpu_to_be_16(uint16_t cpu16)
Convert cpu native uint16_t to 16bit big endian.
#define ODP_UNUSED
Intentionally unused variables of functions.
odp_u32be_t odp_cpu_to_be_32(uint32_t cpu32)
Convert cpu native uint32_t to 32bit big endian.
#define ODP_BIG_ENDIAN
Big endian byte order.
uint32_t odp_be_to_cpu_32(odp_u32be_t be32)
Convert 32bit big endian to cpu native uint32_t.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
int odp_cpumask_first(const odp_cpumask_t *mask)
Find first set CPU in mask.
int odp_cpumask_all_available(odp_cpumask_t *mask)
Report all the available CPUs.
void odp_cpumask_clr(odp_cpumask_t *mask, int cpu)
Remove CPU from mask.
void odp_event_free(odp_event_t event)
Free event.
#define ODP_EVENT_INVALID
Invalid event.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
#define ODP_STATIC_ASSERT(cond, msg)
Compile time assertion macro.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
int odp_pktio_mac_addr(odp_pktio_t pktio, void *mac_addr, int size)
Get the default MAC address of a packet IO interface.
void odp_pktin_queue_param_init(odp_pktin_queue_param_t *param)
Initialize packet input queue parameters.
odp_lso_profile_t odp_lso_profile_create(odp_pktio_t pktio, const odp_lso_profile_param_t *param)
Create LSO profile.
void odp_pktio_param_init(odp_pktio_param_t *param)
Initialize pktio params.
int odp_pktio_promisc_mode(odp_pktio_t pktio)
Determine if promiscuous mode is enabled for a packet IO interface.
int odp_pktio_close(odp_pktio_t pktio)
Close a packet IO interface.
void odp_lso_profile_param_init(odp_lso_profile_param_t *param)
Initialize LSO profile parameters.
#define ODP_LSO_PROFILE_INVALID
Invalid LSO profile handle.
int odp_pktout_queue(odp_pktio_t pktio, odp_pktout_queue_t queues[], int num)
Direct packet output queues.
#define ODP_LSO_MAX_CUSTOM
Maximum number of custom LSO fields supported by ODP API.
int odp_pktio_maxlen_set(odp_pktio_t pktio, uint32_t maxlen_input, uint32_t maxlen_output)
Set maximum frame lengths.
int odp_pktio_promisc_mode_set(odp_pktio_t pktio, odp_bool_t enable)
Set promiscuous mode.
int odp_lso_profile_destroy(odp_lso_profile_t lso_profile)
Destroy LSO profile.
void odp_pktio_config_init(odp_pktio_config_t *config)
Initialize packet IO configuration options.
odp_lso_modify_t
LSO custom modification options.
odp_pktio_t odp_pktio_open(const char *name, odp_pool_t pool, const odp_pktio_param_t *param)
Open a packet IO interface.
int odp_pktout_send_lso(odp_pktout_queue_t queue, const odp_packet_t packet[], int num, const odp_packet_lso_opt_t *lso_opt)
Send packets with segmentation offload.
int odp_pktio_config(odp_pktio_t pktio, const odp_pktio_config_t *config)
Configure packet IO interface options.
void odp_pktio_print(odp_pktio_t pktio)
Print pktio info to the console.
int odp_pktio_start(odp_pktio_t pktio)
Start packet receive and transmit.
#define ODP_PKTIO_INVALID
Invalid packet IO handle.
int odp_pktin_queue(odp_pktio_t pktio, odp_pktin_queue_t queues[], int num)
Direct packet input queues.
void odp_pktout_queue_param_init(odp_pktout_queue_param_t *param)
Initialize packet output queue parameters.
int odp_pktio_stop(odp_pktio_t pktio)
Stop packet receive and transmit.
int odp_pktin_recv(odp_pktin_queue_t queue, odp_packet_t packets[], int num)
Receive packets directly from an interface input queue.
int odp_pktio_index(odp_pktio_t pktio)
Get pktio interface index.
int odp_pktio_capability(odp_pktio_t pktio, odp_pktio_capability_t *capa)
Query packet IO interface capabilities.
#define ODP_PKTIO_MAX_INDEX
Maximum packet IO interface index.
int odp_pktout_send(odp_pktout_queue_t queue, const odp_packet_t packets[], int num)
Send packets directly to an interface output queue.
int odp_pktin_queue_config(odp_pktio_t pktio, const odp_pktin_queue_param_t *param)
Configure packet input queues.
int odp_pktout_queue_config(odp_pktio_t pktio, const odp_pktout_queue_param_t *param)
Configure packet output queues.
@ ODP_LSO_PROTO_IPV4
LSO performs IPv4 fragmentation.
@ ODP_LSO_PROTO_TCP_IPV4
LSO performs TCP segmentation on top of IPv4.
@ ODP_LSO_PROTO_CUSTOM
Custom protocol.
@ ODP_PKTOUT_MODE_DIRECT
Direct packet output on the interface.
@ ODP_PKTOUT_MODE_DISABLED
Application will never send to this interface.
@ ODP_LSO_ADD_SEGMENT_NUM
Add current segment number.
@ ODP_LSO_WRITE_BITS
Write bits in the first, middle and last segment.
@ ODP_LSO_ADD_PAYLOAD_OFFSET
Add number of payload bytes in all previous segments.
@ ODP_LSO_ADD_PAYLOAD_LEN
Add number of payload bytes in the segment.
@ ODP_PKTIO_OP_MT_UNSAFE
Not multithread safe operation.
@ ODP_PKTIN_MODE_DIRECT
Direct packet input from the interface.
@ ODP_PKTIN_MODE_DISABLED
Application will never receive from this interface.
@ ODP_PKTIN_MODE_SCHED
Packet input through scheduler and scheduled event queues.
void odp_packet_from_event_multi(odp_packet_t pkt[], const odp_event_t ev[], int num)
Convert multiple packet events to packet handles.
void odp_packet_has_vlan_qinq_set(odp_packet_t pkt, int val)
Set flag for VLAN QinQ (stacked VLAN)
int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 3 start offset.
int odp_packet_input_index(odp_packet_t pkt)
Packet input interface index.
uint32_t odp_packet_seg_len(odp_packet_t pkt)
Packet data length following the data pointer.
int odp_packet_num_segs(odp_packet_t pkt)
Number of segments.
odp_packet_t odp_packet_copy(odp_packet_t pkt, odp_pool_t pool)
Full copy of a packet.
void * odp_packet_data(odp_packet_t pkt)
Packet data pointer.
int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 4 start offset.
void odp_packet_has_eth_set(odp_packet_t pkt, int val)
Set flag for Ethernet header.
uint32_t odp_packet_len(odp_packet_t pkt)
Packet data length.
odp_packet_t odp_packet_alloc(odp_pool_t pool, uint32_t len)
Allocate a packet from a packet pool.
void odp_packet_has_udp_set(odp_packet_t pkt, int val)
Set flag for UDP.
void odp_packet_free(odp_packet_t pkt)
Free packet.
void odp_packet_free_ctrl_set(odp_packet_t pkt, odp_packet_free_ctrl_t ctrl)
Set packet free control option.
void odp_packet_has_tcp_set(odp_packet_t pkt, int val)
Set flag for TCP.
int odp_packet_copy_from_mem(odp_packet_t pkt, uint32_t offset, uint32_t len, const void *src)
Copy data from memory to packet.
#define ODP_PACKET_INVALID
Invalid packet.
void odp_packet_free_multi(const odp_packet_t pkt[], int num)
Free multiple packets.
void * odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len)
Layer 4 start pointer.
int odp_packet_copy_to_mem(odp_packet_t pkt, uint32_t offset, uint32_t len, void *dst)
Copy data from packet to memory.
odp_packet_t odp_packet_ref_static(odp_packet_t pkt)
Create a static reference to a packet.
void odp_packet_has_vlan_set(odp_packet_t pkt, int val)
Set flag for VLAN.
void odp_packet_has_ipv4_set(odp_packet_t pkt, int val)
Set flag for IPv4.
@ ODP_PACKET_FREE_CTRL_DONT_FREE
Don't free packet after processing it.
@ ODP_PROTO_LAYER_ALL
All layers.
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
int odp_pool_capability(odp_pool_capability_t *capa)
Query pool capabilities.
void odp_pool_param_init(odp_pool_param_t *param)
Initialize pool params.
int odp_pool_destroy(odp_pool_t pool)
Destroy a pool previously created by odp_pool_create()
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_PACKET
Packet pool.
int32_t odp_random_data(uint8_t *buf, uint32_t len, odp_random_kind_t kind)
Generate random byte data.
@ ODP_RANDOM_BASIC
Basic random, presumably pseudo-random generated by SW.
int odp_schedule_multi_no_wait(odp_queue_t *from, odp_event_t events[], int num)
Schedule, do not wait for events.
#define ODP_SCHED_SYNC_PARALLEL
Parallel scheduled queues.
int odp_schedule_default_prio(void)
Default scheduling priority level.
void odp_schedule_pause(void)
Pause scheduling.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
uint64_t odp_schedule_wait_time(uint64_t ns)
Schedule wait time.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
#define ODP_SCHED_GROUP_ALL
Group of all threads.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
#define ODP_SHM_INVALID
Invalid shared memory block.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
bool odp_bool_t
Boolean type.
void odp_sys_info_print(void)
Print system info.
int odp_thread_id(void)
Get thread identifier.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
uint64_t odp_time_to_ns(odp_time_t time)
Convert time to nanoseconds.
#define ODP_TIME_SEC_IN_NS
A second in nanoseconds.
void odp_time_wait_until(odp_time_t time)
Wait until the specified (wall clock) time has been reached.
odp_time_t odp_time_local_from_ns(uint64_t ns)
Convert nanoseconds to local time.
void odp_time_wait_ns(uint64_t ns)
Wait the specified number of nanoseconds.
odp_time_t odp_time_local(void)
Current local time.
#define ODP_TIME_NULL
Zero time stamp.
uint64_t odp_time_local_res(void)
Local time resolution in hertz.
odp_time_t odp_time_global_strict(void)
Current global time (strict)
#define ODP_TIME_MSEC_IN_NS
A millisecond in nanoseconds.
#define ODP_TIME_USEC_IN_NS
A microsecond in nanoseconds.
uint64_t odp_time_diff_ns(odp_time_t t2, odp_time_t t1)
Time difference in nanoseconds.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
odp_feature_t not_used
Unused features.
uint32_t max_payload_len
Maximum payload length per an LSO generated packet (in bytes).
uint32_t max_packet_segments
Maximum number of segments in an input packet.
uint32_t max_segments
Maximum number of segments an LSO operation may create.
uint32_t max_profiles
Maximum number of LSO profiles.
uint32_t max_profiles_per_pktio
Maximum number of LSO profiles per packet IO interface.
uint16_t add_payload_len
ODP_LSO_ADD_PAYLOAD_LEN support.
uint8_t max_num_custom
Maximum number of custom fields supported per LSO profile.
uint16_t write_bits
ODP_LSO_WRITE_BITS support.
uint32_t tcp_ipv4
ODP_LSO_PROTO_TCP_IPV4 support.
uint16_t add_segment_num
ODP_LSO_ADD_SEGMENT_NUM support.
uint32_t ipv4
ODP_LSO_PROTO_IPV4 support.
uint32_t max_payload_offset
Maximum supported offset to the packet payload (in bytes).
struct odp_lso_capability_t::@113 mod_op
Supported LSO custom modification options.
struct odp_lso_capability_t::@114 proto
Supported LSO protocol options.
uint32_t custom
ODP_LSO_PROTO_CUSTOM support.
uint16_t add_payload_offset
ODP_LSO_ADD_PAYLOAD_OFFSET support.
Parameters for ODP_LSO_WRITE_BITS custom operation.
uint8_t value[1]
Value to be written using the mask: new_value[n] = (old_value[n] & ~mask[n]) | (value[n] & mask[n])
uint8_t mask[1]
Bitmask to select which bits to write.
odp_lso_profile_t lso_profile
LSO profile handle.
uint32_t payload_offset
LSO payload offset.
uint32_t max_payload_len
Maximum payload length in an LSO segment.
uint8_t static_ref
Static reference.
Packet input queue parameters.
uint32_t num_queues
Number of input queues to be created.
odp_pktio_op_mode_t op_mode
Operation mode.
odp_queue_param_t queue_param
Queue parameters.
odp_pktin_hash_proto_t hash_proto
Protocol field selection for hashing.
odp_bool_t hash_enable
Enable flow hashing.
struct odp_pktio_capability_t::@117 free_ctrl
Supported packet free control options.
odp_pktio_set_op_t set_op
Supported set operations.
uint32_t max_output
Maximum valid value for 'maxlen_output'.
uint32_t max_input_queues
Maximum number of input queues.
uint32_t max_input
Maximum valid value for 'maxlen_input'.
odp_pktio_config_t config
Supported pktio configuration options.
odp_packet_ref_types_t packet_ref
Supported packet reference types.
struct odp_pktio_capability_t::@115 maxlen
Supported frame lengths for odp_pktio_maxlen_set()
uint32_t min_output
Minimum valid value for 'maxlen_output'.
uint32_t max_output_queues
Maximum number of output queues.
uint32_t dont_free
Packet free control option ODP_PACKET_FREE_CTRL_DONT_FREE support with odp_packet_free_ctrl_set().
uint32_t min_input
Minimum valid value for 'maxlen_input'.
odp_lso_capability_t lso
LSO capabilities.
Packet IO configuration options.
odp_pktout_config_opt_t pktout
Packet output configuration options bit field.
odp_bool_t enable_lso
Enable Large Send Offload (LSO)
odp_pktio_parser_config_t parser
Packet input parser configuration.
odp_pktin_config_opt_t pktin
Packet input configuration options bit field.
odp_pktin_mode_t in_mode
Packet input mode.
odp_pktout_mode_t out_mode
Packet output mode.
odp_proto_layer_t layer
Protocol parsing level in packet input.
Packet output queue parameters.
odp_pktio_op_mode_t op_mode
Operation mode.
uint32_t num_queues
Number of output queues to be created.
uint32_t max_num
Maximum number of buffers of any size.
struct odp_pool_capability_t::@134 pkt
Packet pool capabilities
uint32_t max_seg_len
Maximum packet segment data length in bytes.
uint32_t max_len
Maximum packet data length in bytes.
uint32_t num
Number of buffers in the pool.
struct odp_pool_param_t::@139 pkt
Parameters for packet pools.
odp_pool_type_t type
Pool type.
uint32_t len
Minimum length of 'num' packets.
uint32_t seg_len
Minimum number of packet data bytes that can be stored in the first segment of a newly allocated pack...
odp_schedule_param_t sched
Scheduler parameters.
odp_schedule_group_t group
Thread group.
odp_schedule_prio_t prio
Priority level.
odp_schedule_sync_t sync
Synchronization method.
uint32_t tm
Traffic Manager APIs, e.g., odp_tm_xxx()
uint32_t crypto
Crypto APIs, e.g., odp_crypto_xxx()
uint32_t ipsec
IPsec APIs, e.g., odp_ipsec_xxx()
uint32_t timer
Timer APIs, e.g., odp_timer_xxx(), odp_timeout_xxx()
uint32_t cls
Classifier APIs, e.g., odp_cls_xxx(), odp_cos_xxx()
struct odp_feature_t::@174 feat
Individual feature bits.
uint32_t compress
Compression APIs, e.g., odp_comp_xxx()
uint64_t drop_udp_err
Drop packets with a UDP error on packet input.
struct odp_pktin_config_opt_t::@108 bit
Option flags.
uint64_t udp_chksum
Check UDP checksum on packet input.
uint64_t tcp_chksum
Check TCP checksum on packet input.
uint64_t drop_tcp_err
Drop packets with a TCP error on packet input.
struct odp_pktin_hash_proto_t::@107 proto
Protocol header fields for hashing.
uint32_t ipv4_udp
IPv4 addresses and UDP port numbers.
struct odp_pktio_set_op_t::@112 op
Operation flags.
uint32_t maxlen
Maximum frame length.
uint32_t promisc_mode
Promiscuous mode.
uint64_t tcp_chksum
Insert TCP checksum on packet by default.
struct odp_pktout_config_opt_t::@109 bit
Option flags for packet output.
uint64_t tcp_chksum_ena
Enable TCP checksum insertion.
uint64_t udp_chksum
Insert UDP checksum on packet by default.
uint64_t udp_chksum_ena
Enable UDP checksum insertion.