21 #include <odp/helper/odph_api.h>
23 #include "odp_l3fwd_db.h"
24 #include "odp_l3fwd_lpm.h"
26 #define POOL_NUM_PKT 8192
27 #define POOL_SEG_LEN 1856
28 #define MAX_PKT_BURST 32
30 #define MAX_NB_WORKER (ODP_THREAD_COUNT_MAX - 1)
31 #define MAX_NB_PKTIO 32
32 #define MAX_NB_QUEUE 32
33 #define MAX_NB_QCONFS 1024
34 #define MAX_NB_ROUTE 32
36 #define INVALID_ID (-1)
37 #define PRINT_INTERVAL 1
40 #define NO_PATH(file_name) (strrchr((file_name), '/') ? \
41 strrchr((file_name), '/') + 1 : (file_name))
43 struct l3fwd_pktio_s {
45 odph_ethaddr_t mac_addr;
54 struct l3fwd_qconf_s {
67 int rxq[MAX_NB_QUEUE];
69 } pktio[MAX_NB_PKTIO];
76 char *if_names[MAX_NB_PKTIO];
78 char *route_str[MAX_NB_ROUTE];
79 unsigned int worker_count;
80 struct l3fwd_qconf_s qconf_config[MAX_NB_QCONFS];
81 unsigned int qconf_count;
84 uint8_t dest_mac_changed[MAX_NB_PKTIO];
90 struct l3fwd_pktio_s l3fwd_pktios[MAX_NB_PKTIO];
91 struct thread_arg_s worker_args[MAX_NB_WORKER];
92 odph_ethaddr_t eth_dest_mac[MAX_NB_PKTIO];
104 static global_data_t *global;
106 static int create_pktio(
const char *name,
odp_pool_t pool,
107 struct l3fwd_pktio_s *fwd_pktio)
119 printf(
"Failed to open %s\n", name);
122 fwd_pktio->pktio = pktio;
126 printf(
"Error: pktio %s: unable to read capabilities!\n",
133 config.
parser.
layer = global->cmd_args.error_check ?
145 if (fwd_pktio->nb_rxq > MAX_NB_QUEUE)
146 fwd_pktio->nb_rxq = MAX_NB_QUEUE;
148 if (fwd_pktio->nb_txq > MAX_NB_QUEUE)
149 fwd_pktio->nb_txq = MAX_NB_QUEUE;
154 static void setup_fwd_db(
void)
156 fwd_db_entry_t *entry;
160 args = &global->cmd_args;
162 init_fwd_hash_cache();
166 for (entry = fwd_db->list; NULL != entry; entry = entry->next) {
167 if_idx = entry->oif_id;
168 if (!args->hash_mode)
169 fib_tbl_insert(entry->subnet.addr, if_idx,
170 entry->subnet.depth);
171 if (args->dest_mac_changed[if_idx])
172 global->eth_dest_mac[if_idx] = entry->dst_mac;
174 entry->dst_mac = global->eth_dest_mac[if_idx];
183 static inline void ipv4_dec_ttl_csum_update(odph_ipv4hdr_t *ip)
194 static inline int l3fwd_pkt_hash(
odp_packet_t pkt,
int sif)
196 fwd_db_entry_t *entry;
206 key.proto = ip->proto;
213 udp = (odph_udphdr_t *)ptr;
220 entry = find_fwd_db_entry(&key);
221 ipv4_dec_ttl_csum_update(ip);
224 eth->src = entry->src_mac;
225 eth->dst = entry->dst_mac;
236 static inline int l3fwd_pkt_lpm(
odp_packet_t pkt,
int sif)
244 ipv4_dec_ttl_csum_update(ip);
252 eth->dst = global->eth_dest_mac[dif];
253 eth->src = global->l3fwd_pktios[dif].mac_addr;
269 static inline int drop_err_pkts(
odp_packet_t pkt_tbl[],
unsigned num)
272 unsigned dropped = 0;
276 for (i = 0, j = 0; i < num; ++i) {
280 if (global->cmd_args.error_check)
287 pkt_tbl[j - 1] = pkt;
294 static int run_worker(
void *arg)
297 struct thread_arg_s *thr_arg = arg;
299 int input_ifs[thr_arg->nb_pktio];
304 int pkts, drop, sent;
311 for (i = 0; i < global->cmd_args.if_count; i++) {
312 int txq_idx = thr_arg->pktio[i].txq_idx;
314 output_queues[i] = global->l3fwd_pktios[i].ifout[txq_idx];
316 if_idx = thr_arg->pktio[i].if_idx;
317 for (j = 0; j < thr_arg->pktio[i].nb_rxq; j++) {
318 int rxq_idx = thr_arg->pktio[i].rxq[j];
320 inq = global->l3fwd_pktios[if_idx].ifin[rxq_idx];
321 input_ifs[num_pktio] = if_idx;
322 input_queues[num_pktio] = inq;
328 ODPH_ABORT(
"No pktio devices found\n");
330 if_idx = input_ifs[pktio];
331 inq = input_queues[pktio];
337 if_idx = input_ifs[pktio];
338 inq = input_queues[pktio];
340 if (pktio == num_pktio)
348 thr_arg->packets += pkts;
349 drop = drop_err_pkts(pkt_tbl, pkts);
351 thr_arg->rx_drops += drop;
355 dif = global->fwd_func(pkt_tbl[0], if_idx);
359 for (i = 1; i < pkts; i++) {
360 dif = global->fwd_func(tbl[i], if_idx);
366 sent = sent < 0 ? 0 : sent;
368 thr_arg->tx_drops += i - sent;
384 static int find_port_id_by_name(
char *name, app_args_t *args)
391 for (i = 0; i < args->if_count; i++) {
392 if (!strcmp(name, args->if_names[i]))
400 static int split_string(
char *str,
int stringlen,
401 char **tokens,
int maxtokens,
char delim)
406 if (str == NULL || tokens == NULL)
409 for (i = 0; i < stringlen; i++) {
410 if (str[i] ==
'\0' || tok >= maxtokens)
414 tokens[tok++] = &str[i];
416 if (str[i] == delim) {
428 static int parse_config(
char *cfg_str, app_args_t *args)
431 const char *p, *p0 = cfg_str;
439 unsigned long int_fld[FLD_LAST];
440 char *str_fld[FLD_LAST];
444 struct l3fwd_qconf_s *qconf_array = &args->qconf_config[0];
454 if (size >=
sizeof(s))
457 snprintf(s,
sizeof(s),
"%.*s", size, p);
458 i = split_string(s,
sizeof(s), str_fld, FLD_LAST,
',');
461 for (i = 0; i < FLD_LAST; i++) {
463 int_fld[i] = strtoul(str_fld[i], &end, 0);
464 if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
467 if (nb_qconfs >= MAX_NB_QCONFS) {
468 printf(
"exceeded max number of queue params: %d\n",
472 qconf_array[nb_qconfs].if_idx = (uint8_t)int_fld[FLD_PORT];
473 qconf_array[nb_qconfs].rxq_idx = (uint8_t)int_fld[FLD_QUEUE];
474 qconf_array[nb_qconfs].core_idx = (uint8_t)int_fld[FLD_LCORE];
479 args->qconf_count = nb_qconfs;
484 static void print_usage(
char *progname)
487 "ODP L3 forwarding application.\n"
489 "Usage: %s OPTIONS\n"
490 " E.g. %s -i eth0,eth1 -r 1.1.1.0/24,eth0 -r 2.2.2.0/24,eth1\n"
491 " In the above example,\n"
492 " eth0 will send pkts to eth1 and vice versa\n"
494 "Mandatory OPTIONS:\n"
495 " -i, --interface eth interfaces (comma-separated, no spaces)\n"
496 " -r, --route SubNet,Intf[,NextHopMAC]\n"
497 " NextHopMAC can be optional\n"
499 "Optional OPTIONS:\n"
500 " -s, --style [lpm|hash], ip lookup method\n"
501 " optional, default as lpm\n"
502 " -d, --duration Seconds to run and print stats\n"
503 " optional, default as 0, run forever\n"
504 " -t, --thread Number of threads to do forwarding\n"
505 " 0=all available, default=1\n"
506 " -q, --queue Configure rx queue(s) for port\n"
507 " optional, format: [(port, queue, thread),...]\n"
508 " for example: -q '(0, 0, 1),(1,0,2)'\n"
509 " -e, --error_check 0: Don't check packet errors (default)\n"
510 " 1: Check packet errors\n"
511 " -h, --help Display help and exit.\n\n"
512 "\n", NO_PATH(progname), NO_PATH(progname)
516 static void parse_cmdline_args(
int argc,
char *argv[], app_args_t *args)
520 size_t len, route_index = 0;
524 static struct option longopts[] = {
525 {
"interface", required_argument, NULL,
'i'},
526 {
"route", required_argument, NULL,
'r'},
527 {
"style", required_argument, NULL,
's'},
528 {
"duration", required_argument, NULL,
'd'},
529 {
"thread", required_argument, NULL,
't'},
530 {
"queue", required_argument, NULL,
'q'},
531 {
"error_check", required_argument, NULL,
'e'},
532 {
"help", no_argument, NULL,
'h'},
536 args->worker_count = 1;
539 opt = getopt_long(argc, argv,
"+s:t:d:i:r:q:e:h",
548 if (!strcmp(optarg,
"hash"))
554 args->worker_count = atoi(optarg);
555 if (args->worker_count > i) {
556 printf(
"Too many threads,"
557 "truncate to cpu count: %d\n", i);
558 args->worker_count = i;
565 args->duration = atoi(optarg);
570 len = strlen(optarg);
572 print_usage(argv[0]);
579 print_usage(argv[0]);
582 args->if_names_buf = local;
585 strcpy(local, optarg);
586 for (token = strtok(local,
","), i = 0;
587 token != NULL; token = strtok(NULL,
","), i++) {
588 if (i >= MAX_NB_PKTIO) {
589 printf(
"too many ports specified, "
590 "truncated to %d", MAX_NB_PKTIO);
593 args->if_names[i] = token;
596 print_usage(argv[0]);
605 if (route_index >= MAX_NB_ROUTE) {
606 printf(
"No more routes can be added\n");
609 local = calloc(1, strlen(optarg) + 1);
614 memcpy(local, optarg, strlen(optarg));
615 local[strlen(optarg)] =
'\0';
616 args->route_str[route_index++] = local;
620 args->error_check = atoi(optarg);
624 print_usage(argv[0]);
629 parse_config(optarg, args);
638 if (args->if_count == 0) {
639 printf(
"\nNo option -i specified.\n");
643 if (args->route_str[0] == NULL) {
644 printf(
"\nNo option -r specified.\n");
648 if (mem_failure == 1) {
649 printf(
"\nAllocate memory failure.\n");
656 print_usage(argv[0]);
660 static void print_info(
char *progname, app_args_t *args)
666 printf(
"Running ODP appl: \"%s\"\n"
667 "-----------------\n"
672 args->hash_mode ?
"hash" :
"lpm",
675 for (i = 0; i < args->if_count; ++i)
676 printf(
" %s", args->if_names[i]);
689 static void setup_worker_qconf(app_args_t *args)
691 int j, rxq_idx, pktio;
692 unsigned int i, nb_worker, if_count;
693 struct thread_arg_s *arg;
694 struct l3fwd_pktio_s *port;
695 uint8_t queue_mask[MAX_NB_PKTIO][MAX_NB_QUEUE];
697 nb_worker = args->worker_count;
698 if_count = args->if_count;
701 if (!args->qconf_count) {
702 if (nb_worker > if_count) {
703 for (i = 0; i < nb_worker; i++) {
704 arg = &global->worker_args[i];
707 port = &global->l3fwd_pktios[j];
708 arg->pktio[0].rxq[0] =
709 port->rxq_idx % port->nb_rxq;
710 arg->pktio[0].nb_rxq = 1;
711 arg->pktio[0].if_idx = j;
716 for (i = 0; i < if_count; i++) {
718 arg = &global->worker_args[j];
720 port = &global->l3fwd_pktios[i];
721 rxq_idx = arg->pktio[i].nb_rxq;
722 pktio = arg->nb_pktio;
723 arg->pktio[pktio].rxq[rxq_idx] =
724 port->rxq_idx % port->nb_rxq;
725 arg->pktio[pktio].nb_rxq++;
726 arg->pktio[pktio].if_idx = i;
734 memset(queue_mask, 0,
sizeof(queue_mask));
735 for (i = 0; i < args->qconf_count; i++) {
736 struct l3fwd_qconf_s *q;
738 q = &args->qconf_config[i];
739 if (q->core_idx >= nb_worker || q->if_idx >= if_count)
740 ODPH_ABORT(
"Error queue (%d, %d, %d), max port: %d, "
741 "max core: %d\n", q->if_idx, q->rxq_idx,
742 q->core_idx, args->if_count - 1,
743 args->worker_count - 1);
746 if (queue_mask[q->if_idx][q->rxq_idx])
747 ODPH_ABORT(
"Error queue (%d, %d, %d), reconfig queue\n",
748 q->if_idx, q->rxq_idx, q->core_idx);
749 queue_mask[q->if_idx][q->rxq_idx] = 1;
751 port = &global->l3fwd_pktios[q->if_idx];
752 if (port->rxq_idx < q->rxq_idx)
753 ODPH_ABORT(
"Error queue (%d, %d, %d), queue should be "
754 "in sequence and start from 0, queue %d\n",
755 q->if_idx, q->rxq_idx, q->core_idx,
758 if (q->rxq_idx > port->nb_rxq) {
759 ODPH_ABORT(
"Error queue (%d, %d, %d), max queue %d\n",
760 q->if_idx, q->rxq_idx, q->core_idx,
763 port->rxq_idx = q->rxq_idx + 1;
766 arg = &global->worker_args[q->core_idx];
769 for (j = 0; j < args->if_count; j++) {
770 if (arg->pktio[j].if_idx == q->if_idx)
773 if (j == args->if_count)
776 rxq_idx = arg->pktio[j].nb_rxq;
777 arg->pktio[j].rxq[rxq_idx] = q->rxq_idx;
778 arg->pktio[j].nb_rxq++;
779 arg->pktio[j].if_idx = q->if_idx;
780 arg->thr_idx = q->core_idx;
783 for (i = 0; i < args->worker_count; i++) {
784 arg = &global->worker_args[i];
785 for (j = 0; j < args->if_count; j++) {
786 port = &global->l3fwd_pktios[j];
787 arg->pktio[j].txq_idx =
788 port->txq_idx % port->nb_txq;
794 for (i = 0; i < if_count; i++) {
802 port = &global->l3fwd_pktios[i];
803 name = args->if_names[i];
811 if (port->rxq_idx > port->nb_rxq) {
823 ODPH_ABORT(
"Fail to config input queue for port %s\n",
827 if (port->txq_idx > port->nb_txq) {
832 ODPH_ABORT(
"Fail to config output queue for port %s\n",
838 ODPH_ABORT(
"Fail to set pktin queue for port %s\n",
844 ODPH_ABORT(
"Fail to set pktout queue for port %s\n",
849 static void print_qconf_table(app_args_t *args)
852 int j, k, qid, if_idx;
854 struct thread_arg_s *thr_arg;
856 printf(
"Rx Queue table\n"
857 "-----------------\n"
859 "port/id",
"rxq",
"thread");
861 for (i = 0; i < args->worker_count; i++) {
862 thr_arg = &global->worker_args[i];
863 for (j = 0; j < args->if_count; j++) {
864 if (!thr_arg->pktio[j].nb_rxq)
867 if_idx = thr_arg->pktio[j].if_idx;
868 snprintf(buf, 32,
"%s/%d", args->if_names[if_idx],
870 for (k = 0; k < MAX_NB_QUEUE; k++) {
871 qid = thr_arg->pktio[j].rxq[k];
872 if (qid != INVALID_ID)
873 printf(
"%-32s%-16d%-16d\n", buf, qid,
890 static int print_speed_stats(
int num_workers,
int duration,
int timeout)
893 uint64_t pkts_prev = 0;
895 uint64_t rx_drops, tx_drops;
896 uint64_t maximum_pps = 0;
899 int stats_enabled = 1;
900 int loop_forever = (duration == 0);
915 for (i = 0; i < num_workers; i++) {
916 pkts += global->worker_args[i].packets;
917 rx_drops += global->worker_args[i].rx_drops;
918 tx_drops += global->worker_args[i].tx_drops;
921 pps = (pkts - pkts_prev) / timeout;
922 if (pps > maximum_pps)
924 printf(
"%" PRIu64
" pps, %" PRIu64
" max pps, ", pps,
927 printf(
" %" PRIu64
" rx drops, %" PRIu64
" tx drops\n",
933 }
while (loop_forever || (elapsed < duration));
936 printf(
"TEST RESULT: %" PRIu64
" maximum packets per second.\n",
939 return pkts > 100 ? 0 : -1;
942 int main(
int argc,
char **argv)
944 odph_thread_t thread_tbl[MAX_NB_WORKER];
945 odph_thread_common_param_t thr_common;
946 odph_thread_param_t thr_param[MAX_NB_WORKER];
953 uint8_t mac[ODPH_ETHADDR_LEN];
956 struct thread_arg_s *thr_arg;
960 printf(
"Error: ODP global init failed.\n");
965 printf(
"Error: ODP local init failed.\n");
971 ODP_CACHE_LINE_SIZE, 0);
973 printf(
"Error: shared mem reserve failed.\n");
978 if (global == NULL) {
979 printf(
"Error: shared mem alloc failed.\n");
983 memset(global, 0,
sizeof(global_data_t));
989 for (i = 0; i < MAX_NB_PKTIO; i++) {
990 mac[ODPH_ETHADDR_LEN - 1] = (uint8_t)i;
991 memcpy(global->eth_dest_mac[i].addr, mac, ODPH_ETHADDR_LEN);
995 for (i = 0; i < MAX_NB_WORKER; i++) {
996 thr_arg = &global->worker_args[i];
997 for (j = 0; j < MAX_NB_PKTIO; j++) {
998 thr_arg->thr_idx = INVALID_ID;
999 thr_arg->pktio[j].txq_idx = INVALID_ID;
1000 thr_arg->pktio[j].if_idx = INVALID_ID;
1001 memset(thr_arg->pktio[j].rxq, INVALID_ID,
1002 sizeof(thr_arg->pktio[j].rxq));
1007 args = &global->cmd_args;
1008 parse_cmdline_args(argc, argv, args);
1014 for (i = 0; i < MAX_NB_ROUTE; i++) {
1015 if (args->route_str[i]) {
1016 create_fwd_db_entry(args->route_str[i], &oif, &dst_mac);
1018 printf(
"Error: fail to create route entry.\n");
1022 j = find_port_id_by_name(oif, args);
1024 printf(
"Error: port %s not used.\n", oif);
1029 args->dest_mac_changed[j] = 1;
1033 print_info(NO_PATH(argv[0]), args);
1038 params.
pkt.
len = POOL_SEG_LEN;
1039 params.
pkt.
num = POOL_NUM_PKT;
1045 printf(
"Error: packet pool create failed.\n");
1050 for (i = 0; i < args->if_count; i++) {
1051 struct l3fwd_pktio_s *port;
1054 if_name = args->if_names[i];
1055 port = &global->l3fwd_pktios[i];
1056 if (create_pktio(if_name, pool, port)) {
1057 printf(
"Error: create pktio %s\n", if_name);
1061 resolve_fwd_db(if_name, i, mac);
1062 memcpy(port->mac_addr.addr, mac, ODPH_ETHADDR_LEN);
1067 nb_worker = MAX_NB_WORKER;
1068 if (args->worker_count && args->worker_count < MAX_NB_WORKER)
1069 nb_worker = args->worker_count;
1071 args->worker_count = nb_worker;
1074 setup_worker_qconf(args);
1075 print_qconf_table(args);
1078 if (args->hash_mode)
1079 global->fwd_func = l3fwd_pkt_hash;
1081 global->fwd_func = l3fwd_pkt_lpm;
1084 for (i = 0; i < args->if_count; i++) {
1085 struct l3fwd_pktio_s *port;
1089 if_name = args->if_names[i];
1090 port = &global->l3fwd_pktios[i];
1093 printf(
"unable to start pktio: %s\n", if_name);
1097 sprintf(buf,
"%02x:%02x:%02x:%02x:%02x:%02x",
1098 port->mac_addr.addr[0],
1099 port->mac_addr.addr[1],
1100 port->mac_addr.addr[2],
1101 port->mac_addr.addr[3],
1102 port->mac_addr.addr[4],
1103 port->mac_addr.addr[5]);
1104 printf(
"start pktio: %s, mac %s\n", if_name, buf);
1109 odph_thread_common_param_init(&thr_common);
1110 thr_common.instance = instance;
1111 thr_common.cpumask = &cpumask;
1113 for (i = 0; i < nb_worker; i++) {
1114 odph_thread_param_init(&thr_param[i]);
1115 thr_param[i].start = run_worker;
1116 thr_param[i].arg = &global->worker_args[i];
1120 memset(thread_tbl, 0,
sizeof(thread_tbl));
1121 odph_thread_create(thread_tbl, &thr_common, thr_param, nb_worker);
1123 print_speed_stats(nb_worker, args->duration, PRINT_INTERVAL);
1127 odph_thread_join(thread_tbl, nb_worker);
1130 for (i = 0; i < args->if_count; i++) {
1131 odp_pktio_t pktio = global->l3fwd_pktios[i].pktio;
1134 printf(
"Error: failed to close pktio\n");
1140 free(args->if_names_buf);
1142 for (i = 0; i < MAX_NB_ROUTE; i++)
1143 free(args->route_str[i]);
1147 printf(
"Error: shm free flow_table\n");
1152 printf(
"Error: shm free shm_fwd_db\n");
1157 printf(
"Error: shm free fib_lpm_sub\n");
1162 printf(
"Error: pool destroy\n");
1167 printf(
"Error: shm free global data\n");
1172 printf(
"Error: term local\n");
1177 printf(
"Error: term global\n");
void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val)
Initialize atomic uint32 variable.
uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom)
Load value of atomic uint32 variable.
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable.
void odp_barrier_init(odp_barrier_t *barr, int count)
Initialize barrier with thread count.
void odp_mb_full(void)
Full memory barrier.
void odp_barrier_wait(odp_barrier_t *barr)
Synchronize thread execution on barrier.
#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.
uint16_t odp_be_to_cpu_16(odp_u16be_t be16)
Convert 16bit big endian to cpu native uint16_t.
uint32_t odp_be_to_cpu_32(odp_u32be_t be32)
Convert 32bit big endian to cpu native uint32_t.
int odp_cpu_count(void)
CPU count.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
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.
void odp_pktio_param_init(odp_pktio_param_t *param)
Initialize pktio params.
int odp_pktio_close(odp_pktio_t pktio)
Close a packet IO interface.
int odp_pktout_queue(odp_pktio_t pktio, odp_pktout_queue_t queues[], int num)
Direct packet output queues.
void odp_pktio_config_init(odp_pktio_config_t *config)
Initialize packet IO configuration 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_pktio_config(odp_pktio_t pktio, const odp_pktio_config_t *config)
Configure packet IO interface options.
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_capability(odp_pktio_t pktio, odp_pktio_capability_t *capa)
Query packet IO interface capabilities.
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_PKTIO_OP_MT_UNSAFE
Not multithread safe operation.
@ ODP_PKTIO_OP_MT
Multithread safe operation.
int odp_packet_has_ipv4(odp_packet_t pkt)
Check for IPv4.
int odp_packet_has_error(odp_packet_t pkt)
Check for all parse errors in packet.
void odp_packet_free(odp_packet_t pkt)
Free packet.
void * odp_packet_l2_ptr(odp_packet_t pkt, uint32_t *len)
Layer 2 start pointer.
void * odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len)
Layer 4 start pointer.
int odp_packet_has_tcp(odp_packet_t pkt)
Check for TCP.
void * odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len)
Layer 3 start pointer.
void odp_packet_free_multi(const odp_packet_t pkt[], int num)
Free multiple packets.
int odp_packet_has_udp(odp_packet_t pkt)
Check for UDP.
@ ODP_PROTO_LAYER_ALL
All layers.
@ ODP_PROTO_LAYER_L4
Layer L4 protocols (UDP, TCP, SCTP)
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
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.
odp_shm_t odp_shm_lookup(const char *name)
Lookup for a block of shared memory.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
#define ODP_SHM_INVALID
Invalid shared memory block.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
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.
void odp_sys_info_print(void)
Print system info.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
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_pktin_hash_proto_t hash_proto
Protocol field selection for hashing.
odp_bool_t hash_enable
Enable flow hashing.
uint32_t max_input_queues
Maximum number of input queues.
uint32_t max_output_queues
Maximum number of output queues.
Packet IO configuration options.
odp_pktout_config_opt_t pktout
Packet output configuration options bit field.
odp_pktio_parser_config_t parser
Packet input parser configuration.
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 num
Number of buffers in the pool.
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...
struct odp_pool_param_t::@126 pkt
Parameters for packet pools.
uint32_t ipv4_tcp
IPv4 addresses and TCP port numbers.
uint32_t ipv4_udp
IPv4 addresses and UDP port numbers.
struct odp_pktin_hash_proto_t::@99 proto
Protocol header fields for hashing.
uint32_t ipv4
IPv4 addresses.
struct odp_pktout_config_opt_t::@101 bit
Option flags for packet output.
uint64_t no_packet_refs
Packet references not used on packet output.