/** * Create a pktio handle * * @param dev Name of device to open * @param index Pktio index * @param num_rx Number of RX queues * @param num_tx Number of TX queues * @param pool Pool to associate with device for packet RX/TX * * @retval 0 on success * @retval -1 on failure */ static int create_pktio(const char *dev, int idx, int num_rx, int num_tx, odp_pool_t pool) { odp_pktio_t pktio; odp_pktio_param_t pktio_param; odp_pktio_capability_t capa; odp_pktin_queue_param_t pktin_param; odp_pktout_queue_param_t pktout_param; odp_pktio_op_mode_t mode_rx; odp_pktio_op_mode_t mode_tx; odp_pktio_param_init(&pktio_param); pktio = odp_pktio_open(dev, pool, &pktio_param); if (pktio == ODP_PKTIO_INVALID) { printf("Error: failed to open %s\n", dev); return -1; } printf("created pktio %" PRIu64 " (%s)\n", odp_pktio_to_u64(pktio), dev); if (odp_pktio_capability(pktio, &capa)) { printf("Error: capability query failed %s\n", dev); return -1; } odp_pktin_queue_param_init(&pktin_param); odp_pktout_queue_param_init(&pktout_param); mode_tx = ODP_PKTIO_OP_MT_UNSAFE; mode_rx = ODP_PKTIO_OP_MT_UNSAFE; if (num_rx > (int)capa.max_input_queues) { printf("Sharing %i input queues between %i workers\n", capa.max_input_queues, num_rx); num_rx = capa.max_input_queues; mode_rx = ODP_PKTIO_OP_MT; } if (num_tx > (int)capa.max_output_queues) { printf("Sharing %i output queues between %i workers\n", capa.max_output_queues, num_tx); num_tx = capa.max_output_queues; mode_tx = ODP_PKTIO_OP_MT; } pktin_param.hash_enable = 1; pktin_param.hash_proto.proto.ipv4 = 1; pktin_param.hash_proto.proto.ipv4_tcp = 1; pktin_param.hash_proto.proto.ipv4_udp = 1; pktin_param.num_queues = num_rx; pktin_param.op_mode = mode_rx; pktout_param.op_mode = mode_tx; pktout_param.num_queues = num_tx; if (odp_pktin_queue_config(pktio, &pktin_param)) { printf("Error: input queue config failed %s\n", dev); return -1; } if (odp_pktout_queue_config(pktio, &pktout_param)) { printf("Error: output queue config failed %s\n", dev); return -1; } if (odp_pktin_queue(pktio, gbl_args->pktios[idx].pktin, num_rx) != num_rx) { printf("Error: pktin queue query failed %s\n", dev); return -1; } if (odp_pktout_queue(pktio, gbl_args->pktios[idx].pktout, num_tx) != num_tx) { printf("Error: pktout queue query failed %s\n", dev); return -1; } printf("created %i input and %i output queues on (%s)\n", num_rx, num_tx, dev); gbl_args->pktios[idx].num_rx_queue = num_rx; gbl_args->pktios[idx].num_tx_queue = num_tx; gbl_args->pktios[idx].pktio = pktio; return 0; }
static int ipc_second_process(void) { odp_pktio_t ipc_pktio; odp_pool_param_t params; odp_pool_t pool; odp_packet_t pkt_tbl[MAX_PKT_BURST]; odp_packet_t alloc_pkt; int pkts; int ret; int i; odp_time_t start_cycle; odp_time_t cycle; odp_time_t diff; odp_time_t wait; uint64_t stat_pkts = 0; odp_pktin_queue_t pktin; /* Create packet pool */ memset(¶ms, 0, sizeof(params)); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE; params.type = ODP_POOL_PACKET; pool = odp_pool_create("packet_pool2", ¶ms); if (pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } ipc_pktio = create_pktio(pool); wait = odp_time_local_from_ns(run_time_sec * ODP_TIME_SEC_IN_NS); start_cycle = odp_time_local(); if (odp_pktin_queue(ipc_pktio, &pktin, 1) != 1) { EXAMPLE_ERR("no input queue\n"); return -1; } /* start ipc pktio, i.e. wait until other process connects */ for (;;) { /* 1. exit loop if time specified */ if (run_time_sec) { cycle = odp_time_local(); diff = odp_time_diff(cycle, start_cycle); if (odp_time_cmp(wait, diff) < 0) { printf("timeout exit, run_time_sec %d\n", run_time_sec); goto not_started; } } ret = odp_pktio_start(ipc_pktio); if (!ret) break; } for (;;) { /* exit loop if time specified */ if (run_time_sec) { cycle = odp_time_local(); diff = odp_time_diff(cycle, start_cycle); if (odp_time_cmp(wait, diff) < 0) { EXAMPLE_DBG("exit after %d seconds\n", run_time_sec); break; } } /* recv some packets and change MAGIC to MAGIC_2 */ pkts = odp_pktin_recv(pktin, pkt_tbl, MAX_PKT_BURST); if (pkts <= 0) continue; for (i = 0; i < pkts; i++) { odp_packet_t pkt = pkt_tbl[i]; pkt_head_t head; size_t off; off = odp_packet_l4_offset(pkt); if (off == ODP_PACKET_OFFSET_INVALID) EXAMPLE_ABORT("invalid l4 offset\n"); off += ODPH_UDPHDR_LEN; ret = odp_packet_copy_to_mem(pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable copy out head data"); if (head.magic != TEST_SEQ_MAGIC) EXAMPLE_ABORT("Wrong head magic!"); /* Modify magic number in packet */ head.magic = TEST_SEQ_MAGIC_2; ret = odp_packet_copy_from_mem(pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable to copy in head data"); } /* send all packets back */ ret = ipc_odp_packet_send_or_free(ipc_pktio, pkt_tbl, pkts); if (ret < 0) EXAMPLE_ABORT("can not send packets\n"); stat_pkts += ret; /* alloc packet from local pool, set magic to ALLOC_MAGIC, * and send it.*/ alloc_pkt = odp_packet_alloc(pool, SHM_PKT_POOL_BUF_SIZE); if (alloc_pkt != ODP_PACKET_INVALID) { pkt_head_t head; size_t off; odp_packet_l4_offset_set(alloc_pkt, 30); head.magic = TEST_ALLOC_MAGIC; off = odp_packet_l4_offset(alloc_pkt); off += ODPH_UDPHDR_LEN; ret = odp_packet_copy_from_mem(alloc_pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable to copy in head data"); pkt_tbl[0] = alloc_pkt; ret = ipc_odp_packet_send_or_free(ipc_pktio, pkt_tbl, 1); if (ret < 0) EXAMPLE_ABORT("can not send packets\n"); stat_pkts += 1; } } /* cleanup and exit */ ret = odp_pktio_stop(ipc_pktio); if (ret) { EXAMPLE_DBG("ipc2: odp_pktio_stop error %d\n", ret); return -1; } not_started: ret = odp_pktio_close(ipc_pktio); if (ret) { EXAMPLE_DBG("ipc2: odp_pktio_close error %d\n", ret); return -1; } ret = odp_pool_destroy(pool); if (ret) EXAMPLE_DBG("ipc2: pool_destroy error %d\n", ret); return stat_pkts > 1000 ? 0 : -1; }
/** main() Application entry point * * @param argc int * @param argv[] char* * @return int * */ int main(int argc, char *argv[]) { odph_linux_pthread_t thread_tbl[MAX_WORKERS], dispatcher_thread; appl_args_t params; int core_count, num_workers; odp_cpumask_t cpu_mask; int first_cpu, i; struct pktio_thr_arg pktio_thr_args[MAX_WORKERS]; odp_pktio_param_t pktio_param; odp_pktin_queue_param_t pktin_param; odp_pktout_queue_param_t pktout_param; odp_pktio_t pktio; int port, queue_id; odph_linux_thr_params_t thr_params; odp_instance_t instance; struct pktin_table_s { int num_in_queue; odp_pktin_queue_t in_queue[OFP_PKTIN_QUEUE_MAX]; } pktin_table[OFP_FP_INTERFACE_MAX]; /* Parse and store the application arguments */ parse_args(argc, argv, ¶ms); if (params.if_count > OFP_FP_INTERFACE_MAX) { printf("Error: Invalid number of interfaces: maximum %d\n", OFP_FP_INTERFACE_MAX); exit(EXIT_FAILURE); } if (odp_init_global(&instance, NULL, NULL)) { OFP_ERR("Error: ODP global init failed.\n"); exit(EXIT_FAILURE); } if (odp_init_local(instance, ODP_THREAD_CONTROL)) { OFP_ERR("Error: ODP local init failed.\n"); exit(EXIT_FAILURE); } /* Print both system and application information */ print_info(NO_PATH(argv[0]), ¶ms); core_count = odp_cpu_count(); num_workers = core_count; if (params.core_count && params.core_count < core_count) num_workers = params.core_count; if (num_workers > MAX_WORKERS) num_workers = MAX_WORKERS; /* * By default core #0 runs Linux kernel background tasks. * Start mapping thread from core #1 */ if (num_workers > 1) { num_workers--; first_cpu = 1; } else { OFP_ERR("Burst mode requires multiple cores.\n"); exit(EXIT_FAILURE); } if (num_workers < params.if_count) { OFP_ERR("At least %u fastpath cores required.\n", params.if_count); exit(EXIT_FAILURE); } printf("Num worker threads: %i\n", num_workers); printf("first CPU: %i\n", first_cpu); memset(&app_init_params, 0, sizeof(app_init_params)); app_init_params.linux_core_id = 0; if (ofp_init_global(instance, &app_init_params)) { OFP_ERR("Error: OFP global init failed.\n"); exit(EXIT_FAILURE); } if (ofp_init_local()) { OFP_ERR("Error: OFP local init failed.\n"); exit(EXIT_FAILURE); } odp_pktio_param_init(&pktio_param); pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT; pktio_param.out_mode = ODP_PKTOUT_MODE_DIRECT; odp_pktin_queue_param_init(&pktin_param); pktin_param.op_mode = ODP_PKTIO_OP_MT; pktin_param.hash_enable = 0; pktin_param.hash_proto.all_bits = 0; pktin_param.num_queues = 1; odp_pktout_queue_param_init(&pktout_param); pktout_param.num_queues = 1; pktout_param.op_mode = ODP_PKTIO_OP_MT; for (i = 0; i < params.if_count; i++) { if (ofp_ifnet_create(instance, params.if_names[i], &pktio_param, &pktin_param, &pktout_param) < 0) { OFP_ERR("Failed to init interface %s", params.if_names[i]); exit(EXIT_FAILURE); } pktio = odp_pktio_lookup(params.if_names[i]); if (pktio == ODP_PKTIO_INVALID) { OFP_ERR("Failed locate pktio %s", params.if_names[i]); exit(EXIT_FAILURE); } pktin_table[i].num_in_queue = odp_pktin_queue(pktio, pktin_table[i].in_queue, OFP_PKTIN_QUEUE_MAX); if (pktin_table[i].num_in_queue < 0) { OFP_ERR("Failed get input queues for %s", params.if_names[i]); exit(EXIT_FAILURE); } } memset(thread_tbl, 0, sizeof(thread_tbl)); memset(pktio_thr_args, 0, sizeof(pktio_thr_args)); for (i = 0; i < num_workers; ++i) { pktio_thr_args[i].pkt_func = ofp_eth_vlan_processing; port = i % params.if_count; queue_id = (i / params.if_count) % pktin_table[port].num_in_queue; pktio_thr_args[i].pktin = pktin_table[port].in_queue[queue_id]; odp_cpumask_zero(&cpu_mask); odp_cpumask_set(&cpu_mask, first_cpu + i); thr_params.start = pkt_io_recv; thr_params.arg = &pktio_thr_args[i]; thr_params.thr_type = ODP_THREAD_WORKER; thr_params.instance = instance; odph_linux_pthread_create(&thread_tbl[i], &cpu_mask, &thr_params); } odp_cpumask_zero(&cpu_mask); odp_cpumask_set(&cpu_mask, app_init_params.linux_core_id); thr_params.start = event_dispatcher; thr_params.arg = NULL; thr_params.thr_type = ODP_THREAD_WORKER; thr_params.instance = instance; odph_linux_pthread_create(&dispatcher_thread, &cpu_mask, &thr_params); /* Start CLI */ ofp_start_cli_thread(instance, app_init_params.linux_core_id, params.conf_file); odph_linux_pthread_join(thread_tbl, num_workers); printf("End Main()\n"); return 0; }