/* * Main packet transmit routine. Transmit packets at a fixed rate for * specified length of time. */ static void *run_thread_tx(void *arg) { test_globals_t *globals; int thr_id; odp_queue_t outq; pkt_tx_stats_t *stats; uint64_t next_tx_cycles, end_cycles, cur_cycles; uint64_t burst_gap_cycles; uint32_t batch_len; int unsent_pkts = 0; odp_event_t tx_event[BATCH_LEN_MAX]; uint64_t idle_start = 0; thread_args_t *targs = arg; batch_len = targs->batch_len; if (batch_len > BATCH_LEN_MAX) batch_len = BATCH_LEN_MAX; thr_id = odp_thread_id(); globals = odp_shm_addr(odp_shm_lookup("test_globals")); stats = &globals->tx_stats[thr_id]; outq = odp_pktio_outq_getdef(globals->pktio_tx); if (outq == ODP_QUEUE_INVALID) LOG_ABORT("Failed to get output queue for thread %d\n", thr_id); burst_gap_cycles = odp_time_ns_to_cycles( (ODP_TIME_SEC * 999) / (1000 * targs->pps / (targs->batch_len))); odp_barrier_wait(&globals->tx_barrier); cur_cycles = odp_time_cycles(); next_tx_cycles = cur_cycles; end_cycles = cur_cycles + odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC); while (cur_cycles < end_cycles) { unsigned alloc_cnt = 0, tx_cnt; if (cur_cycles < next_tx_cycles) { cur_cycles = odp_time_cycles(); if (idle_start == 0) idle_start = cur_cycles; continue; } if (idle_start) { stats->s.idle_cycles += odp_time_diff_cycles( idle_start, cur_cycles); idle_start = 0; } next_tx_cycles += burst_gap_cycles; alloc_cnt = alloc_packets(tx_event, batch_len - unsent_pkts); if (alloc_cnt != batch_len) stats->s.alloc_failures++; tx_cnt = send_packets(outq, tx_event, alloc_cnt); unsent_pkts = alloc_cnt - tx_cnt; stats->s.enq_failures += unsent_pkts; stats->s.tx_cnt += tx_cnt; cur_cycles = odp_time_cycles(); } VPRINT(" %02d: TxPkts %-8"PRIu64" EnqFail %-6"PRIu64 " AllocFail %-6"PRIu64" Idle %"PRIu64"ms\n", thr_id, stats->s.tx_cnt, stats->s.enq_failures, stats->s.alloc_failures, odp_time_cycles_to_ns(stats->s.idle_cycles)/1000/1000); return NULL; }
/* * Main packet transmit routine. Transmit packets at a fixed rate for * specified length of time. */ static int run_thread_tx(void *arg) { test_globals_t *globals; int thr_id; odp_pktout_queue_t pktout; pkt_tx_stats_t *stats; odp_time_t cur_time, send_time_end, send_duration; odp_time_t burst_gap_end, burst_gap; uint32_t batch_len; int unsent_pkts = 0; odp_packet_t tx_packet[BATCH_LEN_MAX]; odp_time_t idle_start = ODP_TIME_NULL; thread_args_t *targs = arg; batch_len = targs->batch_len; if (batch_len > BATCH_LEN_MAX) batch_len = BATCH_LEN_MAX; thr_id = odp_thread_id(); globals = odp_shm_addr(odp_shm_lookup("test_globals")); stats = &globals->tx_stats[thr_id]; if (odp_pktout_queue(globals->pktio_tx, &pktout, 1) != 1) LOG_ABORT("Failed to get output queue for thread %d\n", thr_id); burst_gap = odp_time_local_from_ns( ODP_TIME_SEC_IN_NS / (targs->pps / targs->batch_len)); send_duration = odp_time_local_from_ns(targs->duration * ODP_TIME_SEC_IN_NS); odp_barrier_wait(&globals->tx_barrier); cur_time = odp_time_local(); send_time_end = odp_time_sum(cur_time, send_duration); burst_gap_end = cur_time; while (odp_time_cmp(send_time_end, cur_time) > 0) { unsigned alloc_cnt = 0, tx_cnt; if (odp_time_cmp(burst_gap_end, cur_time) > 0) { cur_time = odp_time_local(); if (!odp_time_cmp(idle_start, ODP_TIME_NULL)) idle_start = cur_time; continue; } if (odp_time_cmp(idle_start, ODP_TIME_NULL) > 0) { odp_time_t diff = odp_time_diff(cur_time, idle_start); stats->s.idle_ticks = odp_time_sum(diff, stats->s.idle_ticks); idle_start = ODP_TIME_NULL; } burst_gap_end = odp_time_sum(burst_gap_end, burst_gap); alloc_cnt = alloc_packets(tx_packet, batch_len - unsent_pkts); if (alloc_cnt != batch_len) stats->s.alloc_failures++; tx_cnt = send_packets(pktout, tx_packet, alloc_cnt); unsent_pkts = alloc_cnt - tx_cnt; stats->s.enq_failures += unsent_pkts; stats->s.tx_cnt += tx_cnt; cur_time = odp_time_local(); } VPRINT(" %02d: TxPkts %-8" PRIu64 " EnqFail %-6" PRIu64 " AllocFail %-6" PRIu64 " Idle %" PRIu64 "ms\n", thr_id, stats->s.tx_cnt, stats->s.enq_failures, stats->s.alloc_failures, odp_time_to_ns(stats->s.idle_ticks) / (uint64_t)ODP_TIME_MSEC_IN_NS); return 0; }