> -----Original Message-----
> From: [email protected] [mailto:lng-odp-
> [email protected]] On Behalf Of ext Maxim Uvarov
> Sent: Friday, March 13, 2015 5:04 PM
> To: [email protected]
> Subject: [lng-odp] [PATCHv2 1/2] example: l2fwd print packets per second
>
> Current print in l2fwd is not useful with slow links and
> also it's hard to say how fast does it work. Print pps
> and packets drops.
>
> Signed-off-by: Maxim Uvarov <[email protected]>
> ---
> example/l2fwd/odp_l2fwd.c | 98 ++++++++++++++++++++++++++++++++++--------
> -----
> 1 file changed, 71 insertions(+), 27 deletions(-)
>
> diff --git a/example/l2fwd/odp_l2fwd.c b/example/l2fwd/odp_l2fwd.c
> index d062a72..0299278 100644
> --- a/example/l2fwd/odp_l2fwd.c
> +++ b/example/l2fwd/odp_l2fwd.c
> @@ -73,6 +73,8 @@ typedef struct {
> int if_count; /**< Number of interfaces to be used */
> char **if_names; /**< Array of pointers to interface names */
> int mode; /**< Packet IO mode */
> + int time; /**< Time in seconds to run. */
> + int accuracy; /**< Number of seconds to get and print
> statistics */
> } appl_args_t;
>
> /**
> @@ -104,6 +106,15 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args);
> static void print_info(char *progname, appl_args_t *appl_args);
> static void usage(char *progname);
>
> +/* speed and stats */
> +typedef struct {
> + uint64_t packets[MAX_WORKERS];
> + uint64_t drops[MAX_WORKERS];
> +} stats_t;
> +
> +static stats_t stats;
> +static int exit_threads;
> +
> /**
> * Packet IO worker thread using ODP queues
> *
> @@ -115,8 +126,6 @@ static void *pktio_queue_thread(void *arg)
> odp_queue_t outq_def;
> odp_packet_t pkt;
> odp_event_t ev;
> - unsigned long pkt_cnt = 0;
> - unsigned long err_cnt = 0;
>
> (void)arg;
>
> @@ -125,14 +134,14 @@ static void *pktio_queue_thread(void *arg)
> printf("[%02i] QUEUE mode\n", thr);
>
> /* Loop packets */
> - for (;;) {
> + while (!exit_threads) {
> /* Use schedule to get buf from any input queue */
> ev = odp_schedule(NULL, ODP_SCHED_WAIT);
> pkt = odp_packet_from_event(ev);
>
> /* Drop packets with errors */
> if (odp_unlikely(drop_err_pkts(&pkt, 1) == 0)) {
> - EXAMPLE_ERR("Drop frame - err_cnt:%lu\n", ++err_cnt);
> + stats.drops[thr] += 1;
> continue;
> }
>
> @@ -141,11 +150,7 @@ static void *pktio_queue_thread(void *arg)
> /* Enqueue the packet for output */
> odp_queue_enq(outq_def, ev);
>
> - /* Print packet counts every once in a while */
> - if (odp_unlikely(pkt_cnt++ % 100000 == 0)) {
> - printf(" [%02i] pkt_cnt:%lu\n", thr, pkt_cnt);
> - fflush(NULL);
> - }
> + stats.packets[thr] += 1;
Per thread statistics should be forced to separate cache lines. Now this line
is likely to cause a cache miss per packet due to false sharing.
> }
>
> /* unreachable */
> @@ -186,9 +191,6 @@ static void *pktio_ifburst_thread(void *arg)
> thread_args_t *thr_args;
> int pkts, pkts_ok;
> odp_packet_t pkt_tbl[MAX_PKT_BURST];
> - unsigned long pkt_cnt = 0;
> - unsigned long err_cnt = 0;
> - unsigned long tmp = 0;
> int src_idx, dst_idx;
> odp_pktio_t pktio_src, pktio_dst;
>
> @@ -208,7 +210,7 @@ static void *pktio_ifburst_thread(void *arg)
> odp_pktio_to_u64(pktio_src), odp_pktio_to_u64(pktio_dst));
>
> /* Loop packets */
> - for (;;) {
> + while (!exit_threads) {
> pkts = odp_pktio_recv(pktio_src, pkt_tbl, MAX_PKT_BURST);
> if (pkts <= 0)
> continue;
> @@ -218,23 +220,13 @@ static void *pktio_ifburst_thread(void *arg)
> if (pkts_ok > 0)
> odp_pktio_send(pktio_dst, pkt_tbl, pkts_ok);
>
> - if (odp_unlikely(pkts_ok != pkts)) {
> - err_cnt += pkts-pkts_ok;
> - EXAMPLE_ERR("Dropped frames:%u - err_cnt:%lu\n",
> - pkts-pkts_ok, err_cnt);
> - }
> + if (odp_unlikely(pkts_ok != pkts))
> + stats.drops[thr] += pkts - pkts_ok;
>
> if (pkts_ok == 0)
> continue;
>
> - /* Print packet counts every once in a while */
> - tmp += pkts_ok;
> - if (odp_unlikely(tmp >= 100000 || pkt_cnt == 0)) {
> - pkt_cnt += tmp;
> - tmp = 0;
> - printf(" [%02i] pkt_cnt:%lu\n", thr, pkt_cnt);
> - fflush(NULL);
> - }
> + stats.packets[thr] += pkts_ok;
> }
>
> /* unreachable */
> @@ -295,6 +287,41 @@ static odp_pktio_t create_pktio(const char *dev,
> odp_pool_t pool,
> return pktio;
> }
>
> +static void print_speed_stats(int num_workers, int duration, int timeout)
> +{
> + stats_t old_stats, new_stats;
> + uint64_t pps, maximum_pps = 0;
> + uint64_t errors;
> + int i;
> + int elapsed = 0;
> +
> + do {
> + memcpy(&old_stats, &stats, sizeof(stats_t));
No need to copy two times. One copy, destination pointer ping-pong and time
measurement over the entire loop would do the trick.
-Petri
> + sleep(timeout);
> + memcpy(&new_stats, &stats, sizeof(stats_t));
> +
> + for (i = 0, pps = 0; i < num_workers; i++)
> + pps += new_stats.packets[i] - old_stats.packets[i];
> + pps = pps / timeout;
> + if (pps > maximum_pps)
> + maximum_pps = pps;
> +
> + printf("%" PRIu64 " pps, %" PRIu64 " max pps, ", pps,
> + maximum_pps);
> +
> + for (i = 0, errors = 0; i < num_workers; i++)
> + errors += new_stats.drops[i] - old_stats.drops[i];
> + errors = errors / timeout;
> +
> + printf(" %" PRIu64 " drops\n", errors);
> + elapsed += timeout;
> + } while (elapsed < duration);
> +
> + printf("TEST RESULT: %" PRIu64 " maximum packets per second.\n",
> + maximum_pps);
> + return;
> +}
> +
> /**
> * ODP L2 forwarding main function
> */
> @@ -412,6 +439,11 @@ int main(int argc, char *argv[])
> cpu = odp_cpumask_next(&cpumask, cpu);
> }
>
> + print_speed_stats(num_workers, gbl_args->appl.time,
> + gbl_args->appl.accuracy);
> +
> + exit_threads = 1;
> +
> /* Master thread waits for other threads to exit */
> odph_linux_pthread_join(thread_tbl, num_workers);
>
> @@ -467,16 +499,20 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
> int i;
> static struct option longopts[] = {
> {"count", required_argument, NULL, 'c'},
> + {"time", required_argument, NULL, 't'},
> + {"accuracy", required_argument, NULL, 'a'},
> {"interface", required_argument, NULL, 'i'}, /* return 'i'
> */
> {"mode", required_argument, NULL, 'm'}, /* return 'm'
> */
> {"help", no_argument, NULL, 'h'}, /* return 'h' */
> {NULL, 0, NULL, 0}
> };
>
> + appl_args->time = 0;
> + appl_args->accuracy = 10; /* get and print pps stats each X seconds
> */
> appl_args->mode = -1; /* Invalid, must be changed by parsing */
>
> while (1) {
> - opt = getopt_long(argc, argv, "+c:i:m:h",
> + opt = getopt_long(argc, argv, "+c:+t:+a:i:m:h",
> longopts, &long_index);
>
> if (opt == -1)
> @@ -486,6 +522,12 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
> case 'c':
> appl_args->cpu_count = atoi(optarg);
> break;
> + case 't':
> + appl_args->time = atoi(optarg);
> + break;
> + case 'a':
> + appl_args->accuracy = atoi(optarg);
> + break;
> /* parse packet-io interface names */
> case 'i':
> len = strlen(optarg);
> @@ -612,6 +654,8 @@ static void usage(char *progname)
> "\n"
> "Optional OPTIONS\n"
> " -c, --count <number> CPU count.\n"
> + " -t, --time <number> Time in seconds to run.\n"
> + " -a, --accuracy <number> Time in seconds get print
> statistics.\n"
> " -h, --help Display help and exit.\n\n"
> " environment variables: ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
> " ODP_PKTIO_DISABLE_SOCKET_MMSG\n"
> --
> 1.9.1
>
>
> _______________________________________________
> lng-odp mailing list
> [email protected]
> http://lists.linaro.org/mailman/listinfo/lng-odp
_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp