[PATCHv3] test: linux-gen: add pcap playback test

Message ID 1472457000-5698-1-git-send-email-maxim.uvarov@linaro.org
State New
Headers show

Commit Message

Maxim Uvarov Aug. 29, 2016, 7:50 a.m.
add pcap play back test which takes 2 arguments: 1 - pcap file,
2 - packet mask to match. Intend is to test odp with different
input traffic to check internal implementation functions. In
current case it's test for vlan tag instertion for packet mmap:
pkt_mmap_vlan_insert().

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

---
 v3: fix comments noted by Anders

 test/linux-generic/.gitignore       |   1 +
 test/linux-generic/Makefile.am      |  10 +-
 test/linux-generic/cls/.gitignore   |   1 +
 test/linux-generic/cls/Makefile.am  |  13 ++
 test/linux-generic/cls/cls.c        | 351 ++++++++++++++++++++++++++++++++++++
 test/linux-generic/cls/cls_main.c   |  12 ++
 test/linux-generic/cls/cls_suites.h |   1 +
 test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes
 test/linux-generic/cls/vlan_run.sh  |  49 +++++
 test/linux-generic/m4/configure.m4  |   1 +
 10 files changed, 435 insertions(+), 4 deletions(-)
 create mode 100644 test/linux-generic/cls/.gitignore
 create mode 100644 test/linux-generic/cls/Makefile.am
 create mode 100644 test/linux-generic/cls/cls.c
 create mode 100644 test/linux-generic/cls/cls_main.c
 create mode 100644 test/linux-generic/cls/cls_suites.h
 create mode 100644 test/linux-generic/cls/vlan.pcap
 create mode 100755 test/linux-generic/cls/vlan_run.sh

-- 
2.7.1.250.gff4ea60

Comments

Maxim Uvarov Sept. 6, 2016, 1:14 p.m. | #1
ping.

On 08/29/16 10:50, Maxim Uvarov wrote:
> add pcap play back test which takes 2 arguments: 1 - pcap file,

> 2 - packet mask to match. Intend is to test odp with different

> input traffic to check internal implementation functions. In

> current case it's test for vlan tag instertion for packet mmap:

> pkt_mmap_vlan_insert().

>

> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

> ---

>   v3: fix comments noted by Anders

>

>   test/linux-generic/.gitignore       |   1 +

>   test/linux-generic/Makefile.am      |  10 +-

>   test/linux-generic/cls/.gitignore   |   1 +

>   test/linux-generic/cls/Makefile.am  |  13 ++

>   test/linux-generic/cls/cls.c        | 351 ++++++++++++++++++++++++++++++++++++

>   test/linux-generic/cls/cls_main.c   |  12 ++

>   test/linux-generic/cls/cls_suites.h |   1 +

>   test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes

>   test/linux-generic/cls/vlan_run.sh  |  49 +++++

>   test/linux-generic/m4/configure.m4  |   1 +

>   10 files changed, 435 insertions(+), 4 deletions(-)

>   create mode 100644 test/linux-generic/cls/.gitignore

>   create mode 100644 test/linux-generic/cls/Makefile.am

>   create mode 100644 test/linux-generic/cls/cls.c

>   create mode 100644 test/linux-generic/cls/cls_main.c

>   create mode 100644 test/linux-generic/cls/cls_suites.h

>   create mode 100644 test/linux-generic/cls/vlan.pcap

>   create mode 100755 test/linux-generic/cls/vlan_run.sh

>

> diff --git a/test/linux-generic/.gitignore b/test/linux-generic/.gitignore

> index 5dabf91..f65c7c1 100644

> --- a/test/linux-generic/.gitignore

> +++ b/test/linux-generic/.gitignore

> @@ -1,3 +1,4 @@

>   *.log

>   *.trs

>   tests-validation.env

> +test_out.pcap

> diff --git a/test/linux-generic/Makefile.am b/test/linux-generic/Makefile.am

> index 4660cf0..2554f8e 100644

> --- a/test/linux-generic/Makefile.am

> +++ b/test/linux-generic/Makefile.am

> @@ -1,5 +1,8 @@

>   include $(top_srcdir)/test/Makefile.inc

>   TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/common_plat/validation

> +TEST_EXTENSIONS = .sh

> +

> +dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>   

>   ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_plat/validation/api

>   

> @@ -37,11 +40,14 @@ TESTS = validation/api/pktio/pktio_run.sh \

>   

>   SUBDIRS += validation/api/pktio\

>   	   validation/api/shmem\

> +	   cls\

>   	   pktio_ipc\

>   	   ring

>   

>   if HAVE_PCAP

>   TESTS += validation/api/pktio/pktio_run_pcap.sh

> +TESTS += cls/vlan_run.sh

> +dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap

>   endif

>   if netmap_support

>   TESTS += validation/api/pktio/pktio_run_netmap.sh

> @@ -61,10 +67,6 @@ SUBDIRS += validation/api/pktio

>   endif

>   endif

>   

> -TEST_EXTENSIONS = .sh

> -

> -dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

> -

>   test_SCRIPTS = $(dist_check_SCRIPTS)

>   

>   tests-validation.env:

> diff --git a/test/linux-generic/cls/.gitignore b/test/linux-generic/cls/.gitignore

> new file mode 100644

> index 0000000..5a652b7

> --- /dev/null

> +++ b/test/linux-generic/cls/.gitignore

> @@ -0,0 +1 @@

> +cls_main

> diff --git a/test/linux-generic/cls/Makefile.am b/test/linux-generic/cls/Makefile.am

> new file mode 100644

> index 0000000..43fb0bc

> --- /dev/null

> +++ b/test/linux-generic/cls/Makefile.am

> @@ -0,0 +1,13 @@

> +include ../Makefile.inc

> +

> +noinst_LTLIBRARIES = libtestcls.la

> +libtestcls_la_SOURCES = cls.c

> +libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)

> +

> +test_PROGRAMS = cls_main$(EXEEXT)

> +dist_cls_main_SOURCES = cls_main.c

> +

> +cls_main_LDFLAGS = $(AM_LDFLAGS)

> +cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)

> +

> +noinst_HEADERS = cls_suites.h

> diff --git a/test/linux-generic/cls/cls.c b/test/linux-generic/cls/cls.c

> new file mode 100644

> index 0000000..f6df30a

> --- /dev/null

> +++ b/test/linux-generic/cls/cls.c

> @@ -0,0 +1,351 @@

> +/* Copyright (c) 2016, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include <stdlib.h>

> +#include <string.h>

> +#include <getopt.h>

> +#include <unistd.h>

> +#include <inttypes.h>

> +

> +#include <test_debug.h>

> +

> +#include <odp_api.h>

> +#include <odp/helper/linux.h>

> +#include <odp/helper/eth.h>

> +#include <odp/helper/ip.h>

> +

> +#include <odp_packet_internal.h>

> +

> +#include "cls_suites.h"

> +

> +/** Get rid of path in filename - only for unix-type paths using '/' */

> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \

> +			    strrchr((file_name), '/') + 1 : (file_name))

> +

> +/**

> + * Print usage information

> + */

> +static void usage(char *progname)

> +{

> +	printf("\n"

> +	       "This is test application to verify that linux-generic classifier\n"

> +	       "correctly classifies packets on input. Main intend is add more code\n"

> +	       "coverage for internal functions playing different traffic recorded to\n"

> +	       "pcap files."

> +	       "\n"

> +	       "Usage: %s OPTIONS\n"

> +	       "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"

> +	       "\n"

> +	       "Mandatory OPTIONS:\n"

> +	       "  -i, pcap file name\n"

> +	       "  -e, expected packet bitmask\n"

> +	       "\n", NO_PATH(progname), NO_PATH(progname)

> +	    );

> +}

> +

> +/** @def SHM_PKT_POOL_SIZE

> + * @brief Size of the shared memory block

> + */

> +#define SHM_PKT_POOL_SIZE      512

> +

> +/** @def SHM_PKT_POOL_BUF_SIZE

> + * @brief Buffer size of the packet pool buffer

> + */

> +#define SHM_PKT_POOL_BUF_SIZE  1856

> +

> +/**

> + * Parsed command line application arguments

> + */

> +typedef struct {

> +	char *file_name;     /**< File name for pcap pktio */

> +	odp_pktio_t pktio;  /**< Pktio dev */

> +	input_flags_t expected_bits; /**< Expected bits from test run */

> +} appl_args_t;

> +

> +/**

> + * Grouping of both parsed CL args and thread specific args - alloc together

> + */

> +typedef struct {

> +	/** Application (parsed) arguments */

> +	appl_args_t appl;

> +} args_t;

> +

> +/** Global pointer to args */

> +static args_t *args;

> +/** Fill this bit struct to check which packet fields were classified */

> +static input_flags_t packet_flags;

> +

> +/**

> + * Parse and store the command line arguments

> + *

> + * @param argc       argument count

> + * @param argv[]     argument vector

> + * @param appl_args  Store application arguments here

> + */

> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args)

> +{

> +	int opt;

> +	int long_index;

> +	static const struct option longopts[] = {

> +		{"interface", required_argument, NULL, 'i'},	/* return 'i' */

> +		{"extected", required_argument, NULL, 'e'},	/* return 'e' */

> +		{"help", no_argument, NULL, 'h'},		/* return 'h' */

> +		{NULL, 0, NULL, 0}

> +	};

> +

> +	static const char *shortopts = ":i:e:h";

> +

> +	/* let helper collect its own arguments (e.g. --odph_proc) */

> +	odph_parse_options(argc, argv, shortopts, longopts);

> +

> +	appl_args->file_name = NULL;

> +	opterr = 0; /* do not issue errors on helper options */

> +	appl_args->expected_bits.all = 0;

> +

> +	while (1) {

> +		opt = getopt_long(argc, argv, shortopts, longopts, &long_index);

> +

> +		if (opt == -1)

> +			break;	/* No more options */

> +

> +		switch (opt) {

> +		case 'i':

> +			appl_args->file_name =  optarg;

> +			break;

> +		case 'e':

> +			appl_args->expected_bits.all = atoll(optarg);

> +			break;

> +

> +		case 'h':

> +			usage(argv[0]);

> +			exit(EXIT_SUCCESS);

> +			break;

> +		default:

> +			break;

> +		}

> +	}

> +

> +	if (!appl_args->file_name) {

> +		usage(argv[0]);

> +		exit(EXIT_SUCCESS);

> +	}

> +

> +	optind = 1;		/* reset 'extern optind' from the getopt lib */

> +}

> +

> +/**

> + * Create a pktio handle and configure in/out queues.

> + *

> + * @param fname Name of device to open

> + * @param pool Pool to associate with device for packet RX/TX

> + *

> + * @return The handle of the created pktio object.

> + * @retval ODP_PKTIO_INVALID if the create fails.

> + */

> +static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)

> +{

> +	odp_pktio_t pktio;

> +	int ret;

> +	odp_pktio_param_t pktio_param;

> +	odp_pktin_queue_param_t pktin_param;

> +	char dev[255];

> +

> +	odp_pktio_param_init(&pktio_param);

> +	pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;

> +

> +	memset(dev, 0, 255);

> +	sprintf(dev, "pcap:in=%s:out=test_out.pcap",  fname);

> +

> +	/* Open a packet IO instance */

> +	pktio = odp_pktio_open(dev, pool, &pktio_param);

> +	if (pktio == ODP_PKTIO_INVALID)

> +		LOG_ABORT("Error: pktio create failed for %s\n", dev);

> +

> +	odp_pktin_queue_param_init(&pktin_param);

> +

> +	pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;

> +

> +	if (odp_pktin_queue_config(pktio, &pktin_param))

> +		LOG_ABORT("Error: pktin config failed for %s\n", dev);

> +

> +	if (odp_pktout_queue_config(pktio, NULL))

> +		LOG_ABORT("Error: pktout config failed for %s\n", dev);

> +

> +	ret = odp_pktio_start(pktio);

> +	if (ret != 0)

> +		LOG_ABORT("Error: unable to start %s\n", dev);

> +

> +	printf("  created pktio:%02" PRIu64

> +	       ", dev:%s, queue mode (ATOMIC queues)\n"

> +	       "  \tdefault pktio%02" PRIu64 "\n",

> +	       odp_pktio_to_u64(pktio), dev,

> +	       odp_pktio_to_u64(pktio));

> +

> +	return pktio;

> +}

> +

> +/**

> + * Packet IO loopback worker thread using ODP queues

> + *

> + * @param arg  thread arguments of type 'thread_args_t *'

> + *

> + * @return 0 on success

> + * @return !0 on any error

> + */

> +static int pktio_queue_thread(void *arg ODP_UNUSED)

> +{

> +	int thr = odp_thread_id();

> +	odp_pktout_queue_t pktout;

> +	odp_packet_t pkt;

> +	odp_event_t ev;

> +	uint64_t sched_wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS * 100);

> +

> +	packet_flags.all = 0;

> +

> +	/* Loop packets */

> +	while (1) {

> +		odp_pktio_t pktio_tmp;

> +

> +		ev = odp_schedule(NULL, sched_wait);

> +		if (ev == ODP_EVENT_INVALID)

> +			break;

> +

> +		pkt = odp_packet_from_event(ev);

> +		if (!odp_packet_is_valid(pkt))

> +			continue;

> +

> +		pktio_tmp = odp_packet_input(pkt);

> +

> +		if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {

> +			LOG_ERR("  [%02i] Error: no pktout queue\n", thr);

> +			return -1;

> +		}

> +

> +		/* Extend bits here for more additional tests */

> +		if (odp_packet_has_l2(pkt))

> +			packet_flags.parsed_l2 = 1;

> +		if (odp_packet_has_vlan(pkt))

> +			packet_flags.vlan = 1;

> +

> +		/* Enqueue the packet for output */

> +		if (odp_pktout_send(pktout, &pkt, 1) != 1) {

> +			LOG_ERR("  [%i] Packet send failed.\n", thr);

> +			odp_packet_free(pkt);

> +			continue;

> +		}

> +	}

> +

> +	return 0;

> +}

> +

> +int cls_main(int argc, char *argv[])

> +{

> +	odph_odpthread_t thread_tbl[1];

> +	odp_pool_t pool;

> +	int num_workers;

> +	int i;

> +	int cpu;

> +	odp_cpumask_t cpumask;

> +	char cpumaskstr[ODP_CPUMASK_STR_SIZE];

> +	odp_pool_param_t params;

> +	odp_instance_t instance;

> +	odph_odpthread_params_t thr_params;

> +

> +	args = calloc(1, sizeof(args_t));

> +	if (args == NULL) {

> +		LOG_ERR("Error: args mem alloc failed.\n");

> +		exit(EXIT_FAILURE);

> +	}

> +

> +	parse_args(argc, argv, &args->appl);

> +

> +	/* Init ODP before calling anything else */

> +	if (odp_init_global(&instance, NULL, NULL)) {

> +		LOG_ERR("Error: ODP global init failed.\n");

> +		exit(EXIT_FAILURE);

> +	}

> +

> +	/* Init this thread */

> +	if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

> +		LOG_ERR("Error: ODP local init failed.\n");

> +		exit(EXIT_FAILURE);

> +	}

> +

> +	num_workers = odp_cpumask_default_worker(&cpumask, 1);

> +	(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));

> +

> +	/* Create packet pool */

> +	odp_pool_param_init(&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_pool", &params);

> +	if (pool == ODP_POOL_INVALID) {

> +		LOG_ERR("Error: packet pool create failed.\n");

> +		exit(EXIT_FAILURE);

> +	}

> +

> +	args->appl.pktio = create_pktio(args->appl.file_name, pool);

> +

> +	/* Create and init worker threads */

> +	memset(thread_tbl, 0, sizeof(thread_tbl));

> +

> +	memset(&thr_params, 0, sizeof(thr_params));

> +	thr_params.thr_type = ODP_THREAD_WORKER;

> +	thr_params.instance = instance;

> +

> +	cpu = odp_cpumask_first(&cpumask);

> +	for (i = 0; i < num_workers; ++i) {

> +		odp_cpumask_t thd_mask;

> +		int (*thr_run_func)(void *);

> +

> +		thr_run_func = pktio_queue_thread;

> +		/*

> +		 * Create threads one-by-one instead of all-at-once,

> +		 * because each thread might get different arguments.

> +		 * Calls odp_thread_create(cpu) for each thread

> +		 */

> +		odp_cpumask_zero(&thd_mask);

> +		odp_cpumask_set(&thd_mask, cpu);

> +

> +		thr_params.start = thr_run_func;

> +		thr_params.arg   = &args;

> +

> +		odph_odpthreads_create(&thread_tbl[i], &thd_mask, &thr_params);

> +		cpu = odp_cpumask_next(&cpumask, cpu);

> +	}

> +

> +	/* Master thread waits for other threads to exit */

> +	for (i = 0; i < num_workers; ++i)

> +		odph_odpthreads_join(&thread_tbl[i]);

> +

> +	odp_pktio_stop(args->appl.pktio);

> +	odp_pktio_close(args->appl.pktio);

> +

> +	while (1) {

> +		odp_event_t ev;

> +

> +		ev = odp_schedule(NULL, 0);

> +		if (ev == ODP_EVENT_INVALID)

> +			break;

> +	}

> +

> +	odp_pool_destroy(pool);

> +	odp_term_local();

> +	odp_term_global(instance);

> +

> +	if (packet_flags.all != args->appl.expected_bits.all) {

> +		LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",

> +			packet_flags.all, args->appl.expected_bits.all);

> +		free(args);

> +		return -1;

> +	}

> +

> +	free(args);

> +	return 0;

> +}

> diff --git a/test/linux-generic/cls/cls_main.c b/test/linux-generic/cls/cls_main.c

> new file mode 100644

> index 0000000..40179b9

> --- /dev/null

> +++ b/test/linux-generic/cls/cls_main.c

> @@ -0,0 +1,12 @@

> +/* Copyright (c) 2016, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include "cls_suites.h"

> +

> +int main(int argc, char *argv[])

> +{

> +	return cls_main(argc, argv);

> +}

> diff --git a/test/linux-generic/cls/cls_suites.h b/test/linux-generic/cls/cls_suites.h

> new file mode 100644

> index 0000000..94c9b55

> --- /dev/null

> +++ b/test/linux-generic/cls/cls_suites.h

> @@ -0,0 +1 @@

> +int cls_main(int argc, char *argv[]);

> diff --git a/test/linux-generic/cls/vlan.pcap b/test/linux-generic/cls/vlan.pcap

> new file mode 100644

> index 0000000000000000000000000000000000000000..106ccb682e51495b4025337518a0bce63c2c7681

> GIT binary patch

> literal 9728

> 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

> H$A|v_$relS

>

> literal 0

> HcmV?d00001

>

> diff --git a/test/linux-generic/cls/vlan_run.sh b/test/linux-generic/cls/vlan_run.sh

> new file mode 100755

> index 0000000..7875eaf

> --- /dev/null

> +++ b/test/linux-generic/cls/vlan_run.sh

> @@ -0,0 +1,49 @@

> +#!/bin/sh

> +#

> +# Copyright (c) 2016, Linaro Limited

> +# All rights reserved.

> +#

> +# SPDX-License-Identifier:      BSD-3-Clause

> +#

> +

> +# directories where binary can be found:

> +# -in the validation dir when running make check (intree or out of tree)

> +# -in the script directory, when running after 'make install', or

> +# -in the validation when running standalone intree,

> +# -in the _build directory, when running after 'make distcheck',

> +# -in the current directory.

> +# running stand alone out of tree requires setting PATH

> +PATH=${TEST_DIR}/linux-generic/cls:$PATH

> +PATH=$(dirname $0):$PATH

> +PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH

> +PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH

> +PATH=.:$PATH

> +

> +bin_path=$(which cls_main${EXEEXT})

> +if [ -x "$bin_path" ] ; then

> +	echo "Running with $bin_path"

> +else

> +	echo "Cannot find cls_main${EXEEXT}"

> +	echo "Please set you PATH for it. PATH=$PATH"

> +fi

> +

> +# Test1: find vlan packets in pcap file and test internal pkt_mmap_vlan_insert()

> +#	 function. Load packets from vlan.pcap file and check that classifier

> +#	 set vlan bits fisible with odp_packet_has_vlan().

> +

> +PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`

> +

> +cls_main -i $PCAP -e 4097

> +ret=$?

> +

> +PCAP_IN_SIZE=`stat -c %s $PCAP`

> +PCAP_OUT_SIZE=`stat -c %s test_out.pcap`

> +

> +rm -f test_out.pcap

> +

> +if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; then

> +	echo "Error: status ${ret}, in:${PCAP_IN_SIZE} out:${PCAP_OUT_SIZE}"

> +	exit 3

> +fi

> +

> +echo "PASS: test 1 passed"

> diff --git a/test/linux-generic/m4/configure.m4 b/test/linux-generic/m4/configure.m4

> index 6b92201..1b722f6 100644

> --- a/test/linux-generic/m4/configure.m4

> +++ b/test/linux-generic/m4/configure.m4

> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

>   AC_CONFIG_FILES([test/linux-generic/Makefile

>   		 test/linux-generic/validation/api/shmem/Makefile

>   		 test/linux-generic/validation/api/pktio/Makefile

> +		 test/linux-generic/cls/Makefile

>   		 test/linux-generic/pktio_ipc/Makefile

>   		 test/linux-generic/ring/Makefile

>   		 test/linux-generic/performance/Makefile])
Maxim Uvarov Sept. 8, 2016, 3:51 p.m. | #2
On 8 September 2016 at 18:42, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:

> if no more comments for v3 I think it's ready to be merged.

>

> Maxim.

>

> On 08/29/16 10:50, Maxim Uvarov wrote:

>

>> add pcap play back test which takes 2 arguments: 1 - pcap file,

>> 2 - packet mask to match. Intend is to test odp with different

>> input traffic to check internal implementation functions. In

>> current case it's test for vlan tag instertion for packet mmap:

>> pkt_mmap_vlan_insert().

>>

>> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

>> ---

>>   v3: fix comments noted by Anders

>>

>>   test/linux-generic/.gitignore       |   1 +

>>   test/linux-generic/Makefile.am      |  10 +-

>>   test/linux-generic/cls/.gitignore   |   1 +

>>   test/linux-generic/cls/Makefile.am  |  13 ++

>>   test/linux-generic/cls/cls.c        | 351 ++++++++++++++++++++++++++++++

>> ++++++

>>   test/linux-generic/cls/cls_main.c   |  12 ++

>>   test/linux-generic/cls/cls_suites.h |   1 +

>>   test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes

>>   test/linux-generic/cls/vlan_run.sh  |  49 +++++

>>   test/linux-generic/m4/configure.m4  |   1 +

>>   10 files changed, 435 insertions(+), 4 deletions(-)

>>   create mode 100644 test/linux-generic/cls/.gitignore

>>   create mode 100644 test/linux-generic/cls/Makefile.am

>>   create mode 100644 test/linux-generic/cls/cls.c

>>   create mode 100644 test/linux-generic/cls/cls_main.c

>>   create mode 100644 test/linux-generic/cls/cls_suites.h

>>   create mode 100644 test/linux-generic/cls/vlan.pcap

>>   create mode 100755 test/linux-generic/cls/vlan_run.sh

>>

>> diff --git a/test/linux-generic/.gitignore b/test/linux-generic/.gitignor

>> e

>> index 5dabf91..f65c7c1 100644

>> --- a/test/linux-generic/.gitignore

>> +++ b/test/linux-generic/.gitignore

>> @@ -1,3 +1,4 @@

>>   *.log

>>   *.trs

>>   tests-validation.env

>> +test_out.pcap

>> diff --git a/test/linux-generic/Makefile.am

>> b/test/linux-generic/Makefile.am

>> index 4660cf0..2554f8e 100644

>> --- a/test/linux-generic/Makefile.am

>> +++ b/test/linux-generic/Makefile.am

>> @@ -1,5 +1,8 @@

>>   include $(top_srcdir)/test/Makefile.inc

>>   TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/

>> common_plat/validation

>> +TEST_EXTENSIONS = .sh

>> +

>> +dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>>     ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_pl

>> at/validation/api

>>   @@ -37,11 +40,14 @@ TESTS = validation/api/pktio/pktio_run.sh \

>>     SUBDIRS += validation/api/pktio\

>>            validation/api/shmem\

>> +          cls\

>>            pktio_ipc\

>>            ring

>>     if HAVE_PCAP

>>   TESTS += validation/api/pktio/pktio_run_pcap.sh

>> +TESTS += cls/vlan_run.sh

>> +dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap

>>   endif

>>   if netmap_support

>>   TESTS += validation/api/pktio/pktio_run_netmap.sh

>> @@ -61,10 +67,6 @@ SUBDIRS += validation/api/pktio

>>   endif

>>   endif

>>   -TEST_EXTENSIONS = .sh

>> -

>> -dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>> -

>>   test_SCRIPTS = $(dist_check_SCRIPTS)

>>     tests-validation.env:

>> diff --git a/test/linux-generic/cls/.gitignore

>> b/test/linux-generic/cls/.gitignore

>> new file mode 100644

>> index 0000000..5a652b7

>> --- /dev/null

>> +++ b/test/linux-generic/cls/.gitignore

>> @@ -0,0 +1 @@

>> +cls_main

>> diff --git a/test/linux-generic/cls/Makefile.am

>> b/test/linux-generic/cls/Makefile.am

>> new file mode 100644

>> index 0000000..43fb0bc

>> --- /dev/null

>> +++ b/test/linux-generic/cls/Makefile.am

>> @@ -0,0 +1,13 @@

>> +include ../Makefile.inc

>> +

>> +noinst_LTLIBRARIES = libtestcls.la

>> +libtestcls_la_SOURCES = cls.c

>> +libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)

>> +

>> +test_PROGRAMS = cls_main$(EXEEXT)

>> +dist_cls_main_SOURCES = cls_main.c

>> +

>> +cls_main_LDFLAGS = $(AM_LDFLAGS)

>> +cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)

>> +

>> +noinst_HEADERS = cls_suites.h

>> diff --git a/test/linux-generic/cls/cls.c b/test/linux-generic/cls/cls.c

>> new file mode 100644

>> index 0000000..f6df30a

>> --- /dev/null

>> +++ b/test/linux-generic/cls/cls.c

>> @@ -0,0 +1,351 @@

>> +/* Copyright (c) 2016, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include <stdlib.h>

>> +#include <string.h>

>> +#include <getopt.h>

>> +#include <unistd.h>

>> +#include <inttypes.h>

>> +

>> +#include <test_debug.h>

>> +

>> +#include <odp_api.h>

>> +#include <odp/helper/linux.h>

>> +#include <odp/helper/eth.h>

>> +#include <odp/helper/ip.h>

>> +

>> +#include <odp_packet_internal.h>

>> +

>> +#include "cls_suites.h"

>> +

>> +/** Get rid of path in filename - only for unix-type paths using '/' */

>> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \

>> +                           strrchr((file_name), '/') + 1 : (file_name))

>> +

>> +/**

>> + * Print usage information

>> + */

>> +static void usage(char *progname)

>> +{

>> +       printf("\n"

>> +              "This is test application to verify that linux-generic

>> classifier\n"

>> +              "correctly classifies packets on input. Main intend is add

>> more code\n"

>> +              "coverage for internal functions playing different traffic

>> recorded to\n"

>> +              "pcap files."

>> +              "\n"

>> +              "Usage: %s OPTIONS\n"

>> +              "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"

>> +              "\n"

>> +              "Mandatory OPTIONS:\n"

>> +              "  -i, pcap file name\n"

>> +              "  -e, expected packet bitmask\n"

>> +              "\n", NO_PATH(progname), NO_PATH(progname)

>> +           );

>> +}

>> +

>> +/** @def SHM_PKT_POOL_SIZE

>> + * @brief Size of the shared memory block

>> + */

>> +#define SHM_PKT_POOL_SIZE      512

>> +

>> +/** @def SHM_PKT_POOL_BUF_SIZE

>> + * @brief Buffer size of the packet pool buffer

>> + */

>> +#define SHM_PKT_POOL_BUF_SIZE  1856

>> +

>> +/**

>> + * Parsed command line application arguments

>> + */

>> +typedef struct {

>> +       char *file_name;     /**< File name for pcap pktio */

>> +       odp_pktio_t pktio;  /**< Pktio dev */

>> +       input_flags_t expected_bits; /**< Expected bits from test run */

>> +} appl_args_t;

>> +

>> +/**

>> + * Grouping of both parsed CL args and thread specific args - alloc

>> together

>> + */

>> +typedef struct {

>> +       /** Application (parsed) arguments */

>> +       appl_args_t appl;

>> +} args_t;

>> +

>> +/** Global pointer to args */

>> +static args_t *args;

>> +/** Fill this bit struct to check which packet fields were classified */

>> +static input_flags_t packet_flags;

>> +

>> +/**

>> + * Parse and store the command line arguments

>> + *

>> + * @param argc       argument count

>> + * @param argv[]     argument vector

>> + * @param appl_args  Store application arguments here

>> + */

>> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args)

>> +{

>> +       int opt;

>> +       int long_index;

>> +       static const struct option longopts[] = {

>> +               {"interface", required_argument, NULL, 'i'},    /* return

>> 'i' */

>> +               {"extected", required_argument, NULL, 'e'},     /* return

>> 'e' */

>> +               {"help", no_argument, NULL, 'h'},               /* return

>> 'h' */

>> +               {NULL, 0, NULL, 0}

>> +       };

>> +

>> +       static const char *shortopts = ":i:e:h";

>> +

>> +       /* let helper collect its own arguments (e.g. --odph_proc) */

>> +       odph_parse_options(argc, argv, shortopts, longopts);

>> +

>> +       appl_args->file_name = NULL;

>> +       opterr = 0; /* do not issue errors on helper options */

>> +       appl_args->expected_bits.all = 0;

>> +

>> +       while (1) {

>> +               opt = getopt_long(argc, argv, shortopts, longopts,

>> &long_index);

>> +

>> +               if (opt == -1)

>> +                       break;  /* No more options */

>> +

>> +               switch (opt) {

>> +               case 'i':

>> +                       appl_args->file_name =  optarg;

>> +                       break;

>> +               case 'e':

>> +                       appl_args->expected_bits.all = atoll(optarg);

>> +                       break;

>> +

>> +               case 'h':

>> +                       usage(argv[0]);

>> +                       exit(EXIT_SUCCESS);

>> +                       break;

>> +               default:

>> +                       break;

>> +               }

>> +       }

>> +

>> +       if (!appl_args->file_name) {

>> +               usage(argv[0]);

>> +               exit(EXIT_SUCCESS);

>> +       }

>> +

>> +       optind = 1;             /* reset 'extern optind' from the getopt

>> lib */

>> +}

>> +

>> +/**

>> + * Create a pktio handle and configure in/out queues.

>> + *

>> + * @param fname Name of device to open

>> + * @param pool Pool to associate with device for packet RX/TX

>> + *

>> + * @return The handle of the created pktio object.

>> + * @retval ODP_PKTIO_INVALID if the create fails.

>> + */

>> +static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)

>> +{

>> +       odp_pktio_t pktio;

>> +       int ret;

>> +       odp_pktio_param_t pktio_param;

>> +       odp_pktin_queue_param_t pktin_param;

>> +       char dev[255];

>> +

>> +       odp_pktio_param_init(&pktio_param);

>> +       pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;

>> +

>> +       memset(dev, 0, 255);

>> +       sprintf(dev, "pcap:in=%s:out=test_out.pcap",  fname);

>> +

>> +       /* Open a packet IO instance */

>> +       pktio = odp_pktio_open(dev, pool, &pktio_param);

>> +       if (pktio == ODP_PKTIO_INVALID)

>> +               LOG_ABORT("Error: pktio create failed for %s\n", dev);

>> +

>> +       odp_pktin_queue_param_init(&pktin_param);

>> +

>> +       pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;

>> +

>> +       if (odp_pktin_queue_config(pktio, &pktin_param))

>> +               LOG_ABORT("Error: pktin config failed for %s\n", dev);

>> +

>> +       if (odp_pktout_queue_config(pktio, NULL))

>> +               LOG_ABORT("Error: pktout config failed for %s\n", dev);

>> +

>> +       ret = odp_pktio_start(pktio);

>> +       if (ret != 0)

>> +               LOG_ABORT("Error: unable to start %s\n", dev);

>> +

>> +       printf("  created pktio:%02" PRIu64

>> +              ", dev:%s, queue mode (ATOMIC queues)\n"

>> +              "  \tdefault pktio%02" PRIu64 "\n",

>> +              odp_pktio_to_u64(pktio), dev,

>> +              odp_pktio_to_u64(pktio));

>> +

>> +       return pktio;

>> +}

>> +

>> +/**

>> + * Packet IO loopback worker thread using ODP queues

>> + *

>> + * @param arg  thread arguments of type 'thread_args_t *'

>> + *

>> + * @return 0 on success

>> + * @return !0 on any error

>> + */

>> +static int pktio_queue_thread(void *arg ODP_UNUSED)

>> +{

>> +       int thr = odp_thread_id();

>> +       odp_pktout_queue_t pktout;

>> +       odp_packet_t pkt;

>> +       odp_event_t ev;

>> +       uint64_t sched_wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS

>> * 100);

>> +

>> +       packet_flags.all = 0;

>> +

>> +       /* Loop packets */

>> +       while (1) {

>> +               odp_pktio_t pktio_tmp;

>> +

>> +               ev = odp_schedule(NULL, sched_wait);

>> +               if (ev == ODP_EVENT_INVALID)

>> +                       break;

>> +

>> +               pkt = odp_packet_from_event(ev);

>> +               if (!odp_packet_is_valid(pkt))

>> +                       continue;

>> +

>> +               pktio_tmp = odp_packet_input(pkt);

>> +

>> +               if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {

>> +                       LOG_ERR("  [%02i] Error: no pktout queue\n", thr);

>> +                       return -1;

>> +               }

>> +

>> +               /* Extend bits here for more additional tests */

>> +               if (odp_packet_has_l2(pkt))

>> +                       packet_flags.parsed_l2 = 1;

>> +               if (odp_packet_has_vlan(pkt))

>> +                       packet_flags.vlan = 1;

>> +

>> +               /* Enqueue the packet for output */

>> +               if (odp_pktout_send(pktout, &pkt, 1) != 1) {

>> +                       LOG_ERR("  [%i] Packet send failed.\n", thr);

>> +                       odp_packet_free(pkt);

>> +                       continue;

>> +               }

>> +       }

>> +

>> +       return 0;

>> +}

>> +

>> +int cls_main(int argc, char *argv[])

>> +{

>> +       odph_odpthread_t thread_tbl[1];

>> +       odp_pool_t pool;

>> +       int num_workers;

>> +       int i;

>> +       int cpu;

>> +       odp_cpumask_t cpumask;

>> +       char cpumaskstr[ODP_CPUMASK_STR_SIZE];

>> +       odp_pool_param_t params;

>> +       odp_instance_t instance;

>> +       odph_odpthread_params_t thr_params;

>> +

>> +       args = calloc(1, sizeof(args_t));

>> +       if (args == NULL) {

>> +               LOG_ERR("Error: args mem alloc failed.\n");

>> +               exit(EXIT_FAILURE);

>> +       }

>> +

>> +       parse_args(argc, argv, &args->appl);

>> +

>> +       /* Init ODP before calling anything else */

>> +       if (odp_init_global(&instance, NULL, NULL)) {

>> +               LOG_ERR("Error: ODP global init failed.\n");

>> +               exit(EXIT_FAILURE);

>> +       }

>> +

>> +       /* Init this thread */

>> +       if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

>> +               LOG_ERR("Error: ODP local init failed.\n");

>> +               exit(EXIT_FAILURE);

>> +       }

>> +

>> +       num_workers = odp_cpumask_default_worker(&cpumask, 1);

>> +       (void)odp_cpumask_to_str(&cpumask, cpumaskstr,

>> sizeof(cpumaskstr));

>> +

>> +       /* Create packet pool */

>> +       odp_pool_param_init(&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_pool", &params);

>> +       if (pool == ODP_POOL_INVALID) {

>> +               LOG_ERR("Error: packet pool create failed.\n");

>> +               exit(EXIT_FAILURE);

>> +       }

>> +

>> +       args->appl.pktio = create_pktio(args->appl.file_name, pool);

>> +

>> +       /* Create and init worker threads */

>> +       memset(thread_tbl, 0, sizeof(thread_tbl));

>> +

>> +       memset(&thr_params, 0, sizeof(thr_params));

>> +       thr_params.thr_type = ODP_THREAD_WORKER;

>> +       thr_params.instance = instance;

>> +

>> +       cpu = odp_cpumask_first(&cpumask);

>> +       for (i = 0; i < num_workers; ++i) {

>> +               odp_cpumask_t thd_mask;

>> +               int (*thr_run_func)(void *);

>> +

>> +               thr_run_func = pktio_queue_thread;

>> +               /*

>> +                * Create threads one-by-one instead of all-at-once,

>> +                * because each thread might get different arguments.

>> +                * Calls odp_thread_create(cpu) for each thread

>> +                */

>> +               odp_cpumask_zero(&thd_mask);

>> +               odp_cpumask_set(&thd_mask, cpu);

>> +

>> +               thr_params.start = thr_run_func;

>> +               thr_params.arg   = &args;

>> +

>> +               odph_odpthreads_create(&thread_tbl[i], &thd_mask,

>> &thr_params);

>> +               cpu = odp_cpumask_next(&cpumask, cpu);

>> +       }

>> +

>> +       /* Master thread waits for other threads to exit */

>> +       for (i = 0; i < num_workers; ++i)

>> +               odph_odpthreads_join(&thread_tbl[i]);

>> +

>> +       odp_pktio_stop(args->appl.pktio);

>> +       odp_pktio_close(args->appl.pktio);

>> +

>> +       while (1) {

>> +               odp_event_t ev;

>> +

>> +               ev = odp_schedule(NULL, 0);

>> +               if (ev == ODP_EVENT_INVALID)

>> +                       break;

>> +       }

>> +

>> +       odp_pool_destroy(pool);

>> +       odp_term_local();

>> +       odp_term_global(instance);

>> +

>> +       if (packet_flags.all != args->appl.expected_bits.all) {

>> +               LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",

>> +                       packet_flags.all, args->appl.expected_bits.all);

>> +               free(args);

>> +               return -1;

>> +       }

>> +

>> +       free(args);

>> +       return 0;

>> +}

>> diff --git a/test/linux-generic/cls/cls_main.c

>> b/test/linux-generic/cls/cls_main.c

>> new file mode 100644

>> index 0000000..40179b9

>> --- /dev/null

>> +++ b/test/linux-generic/cls/cls_main.c

>> @@ -0,0 +1,12 @@

>> +/* Copyright (c) 2016, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include "cls_suites.h"

>> +

>> +int main(int argc, char *argv[])

>> +{

>> +       return cls_main(argc, argv);

>> +}

>> diff --git a/test/linux-generic/cls/cls_suites.h

>> b/test/linux-generic/cls/cls_suites.h

>> new file mode 100644

>> index 0000000..94c9b55

>> --- /dev/null

>> +++ b/test/linux-generic/cls/cls_suites.h

>> @@ -0,0 +1 @@

>> +int cls_main(int argc, char *argv[]);

>> diff --git a/test/linux-generic/cls/vlan.pcap

>> b/test/linux-generic/cls/vlan.pcap

>> new file mode 100644

>> index 0000000000000000000000000000000000000000..106ccb682e51495b40

>> 25337518a0bce63c2c7681

>> GIT binary patch

>> literal 9728

>> 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

>> H$A|v_$relS

>>

>> literal 0

>> HcmV?d00001

>>

>> diff --git a/test/linux-generic/cls/vlan_run.sh

>> b/test/linux-generic/cls/vlan_run.sh

>> new file mode 100755

>> index 0000000..7875eaf

>> --- /dev/null

>> +++ b/test/linux-generic/cls/vlan_run.sh

>> @@ -0,0 +1,49 @@

>> +#!/bin/sh

>> +#

>> +# Copyright (c) 2016, Linaro Limited

>> +# All rights reserved.

>> +#

>> +# SPDX-License-Identifier:      BSD-3-Clause

>> +#

>> +

>> +# directories where binary can be found:

>> +# -in the validation dir when running make check (intree or out of tree)

>> +# -in the script directory, when running after 'make install', or

>> +# -in the validation when running standalone intree,

>> +# -in the _build directory, when running after 'make distcheck',

>> +# -in the current directory.

>> +# running stand alone out of tree requires setting PATH

>> +PATH=${TEST_DIR}/linux-generic/cls:$PATH

>> +PATH=$(dirname $0):$PATH

>> +PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH

>> +PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH

>> +PATH=.:$PATH

>> +

>> +bin_path=$(which cls_main${EXEEXT})

>> +if [ -x "$bin_path" ] ; then

>> +       echo "Running with $bin_path"

>> +else

>> +       echo "Cannot find cls_main${EXEEXT}"

>> +       echo "Please set you PATH for it. PATH=$PATH"

>> +fi

>> +

>> +# Test1: find vlan packets in pcap file and test internal

>> pkt_mmap_vlan_insert()

>> +#       function. Load packets from vlan.pcap file and check that

>> classifier

>> +#       set vlan bits fisible with odp_packet_has_vlan().

>> +

>> +PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`

>> +

>> +cls_main -i $PCAP -e 4097

>> +ret=$?

>> +

>> +PCAP_IN_SIZE=`stat -c %s $PCAP`

>> +PCAP_OUT_SIZE=`stat -c %s test_out.pcap`

>> +

>> +rm -f test_out.pcap

>> +

>> +if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; then

>> +       echo "Error: status ${ret}, in:${PCAP_IN_SIZE}

>> out:${PCAP_OUT_SIZE}"

>> +       exit 3

>> +fi

>> +

>> +echo "PASS: test 1 passed"

>> diff --git a/test/linux-generic/m4/configure.m4

>> b/test/linux-generic/m4/configure.m4

>> index 6b92201..1b722f6 100644

>> --- a/test/linux-generic/m4/configure.m4

>> +++ b/test/linux-generic/m4/configure.m4

>> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

>>   AC_CONFIG_FILES([test/linux-generic/Makefile

>>                  test/linux-generic/validation/api/shmem/Makefile

>>                  test/linux-generic/validation/api/pktio/Makefile

>> +                test/linux-generic/cls/Makefile

>>                  test/linux-generic/pktio_ipc/Makefile

>>                  test/linux-generic/ring/Makefile

>>                  test/linux-generic/performance/Makefile])

>>

>

>
Maxim Uvarov Sept. 12, 2016, 2:43 p.m. | #3
if no comments than it can be merged?

Maxim.

On 08/29/16 10:50, Maxim Uvarov wrote:
> add pcap play back test which takes 2 arguments: 1 - pcap file,

> 2 - packet mask to match. Intend is to test odp with different

> input traffic to check internal implementation functions. In

> current case it's test for vlan tag instertion for packet mmap:

> pkt_mmap_vlan_insert().

>

> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

> ---

>   v3: fix comments noted by Anders

>

>   test/linux-generic/.gitignore       |   1 +

>   test/linux-generic/Makefile.am      |  10 +-

>   test/linux-generic/cls/.gitignore   |   1 +

>   test/linux-generic/cls/Makefile.am  |  13 ++

>   test/linux-generic/cls/cls.c        | 351 ++++++++++++++++++++++++++++++++++++

>   test/linux-generic/cls/cls_main.c   |  12 ++

>   test/linux-generic/cls/cls_suites.h |   1 +

>   test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes

>   test/linux-generic/cls/vlan_run.sh  |  49 +++++

>   test/linux-generic/m4/configure.m4  |   1 +

>   10 files changed, 435 insertions(+), 4 deletions(-)

>   create mode 100644 test/linux-generic/cls/.gitignore

>   create mode 100644 test/linux-generic/cls/Makefile.am

>   create mode 100644 test/linux-generic/cls/cls.c

>   create mode 100644 test/linux-generic/cls/cls_main.c

>   create mode 100644 test/linux-generic/cls/cls_suites.h

>   create mode 100644 test/linux-generic/cls/vlan.pcap

>   create mode 100755 test/linux-generic/cls/vlan_run.sh

>

> diff --git a/test/linux-generic/.gitignore b/test/linux-generic/.gitignore

> index 5dabf91..f65c7c1 100644

> --- a/test/linux-generic/.gitignore

> +++ b/test/linux-generic/.gitignore

> @@ -1,3 +1,4 @@

>   *.log

>   *.trs

>   tests-validation.env

> +test_out.pcap

> diff --git a/test/linux-generic/Makefile.am b/test/linux-generic/Makefile.am

> index 4660cf0..2554f8e 100644

> --- a/test/linux-generic/Makefile.am

> +++ b/test/linux-generic/Makefile.am

> @@ -1,5 +1,8 @@

>   include $(top_srcdir)/test/Makefile.inc

>   TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/common_plat/validation

> +TEST_EXTENSIONS = .sh

> +

> +dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>   

>   ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_plat/validation/api

>   

> @@ -37,11 +40,14 @@ TESTS = validation/api/pktio/pktio_run.sh \

>   

>   SUBDIRS += validation/api/pktio\

>   	   validation/api/shmem\

> +	   cls\

>   	   pktio_ipc\

>   	   ring

>   

>   if HAVE_PCAP

>   TESTS += validation/api/pktio/pktio_run_pcap.sh

> +TESTS += cls/vlan_run.sh

> +dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap

>   endif

>   if netmap_support

>   TESTS += validation/api/pktio/pktio_run_netmap.sh

> @@ -61,10 +67,6 @@ SUBDIRS += validation/api/pktio

>   endif

>   endif

>   

> -TEST_EXTENSIONS = .sh

> -

> -dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

> -

>   test_SCRIPTS = $(dist_check_SCRIPTS)

>   

>   tests-validation.env:

> diff --git a/test/linux-generic/cls/.gitignore b/test/linux-generic/cls/.gitignore

> new file mode 100644

> index 0000000..5a652b7

> --- /dev/null

> +++ b/test/linux-generic/cls/.gitignore

> @@ -0,0 +1 @@

> +cls_main

> diff --git a/test/linux-generic/cls/Makefile.am b/test/linux-generic/cls/Makefile.am

> new file mode 100644

> index 0000000..43fb0bc

> --- /dev/null

> +++ b/test/linux-generic/cls/Makefile.am

> @@ -0,0 +1,13 @@

> +include ../Makefile.inc

> +

> +noinst_LTLIBRARIES = libtestcls.la

> +libtestcls_la_SOURCES = cls.c

> +libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)

> +

> +test_PROGRAMS = cls_main$(EXEEXT)

> +dist_cls_main_SOURCES = cls_main.c

> +

> +cls_main_LDFLAGS = $(AM_LDFLAGS)

> +cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)

> +

> +noinst_HEADERS = cls_suites.h

> diff --git a/test/linux-generic/cls/cls.c b/test/linux-generic/cls/cls.c

> new file mode 100644

> index 0000000..f6df30a

> --- /dev/null

> +++ b/test/linux-generic/cls/cls.c

> @@ -0,0 +1,351 @@

> +/* Copyright (c) 2016, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include <stdlib.h>

> +#include <string.h>

> +#include <getopt.h>

> +#include <unistd.h>

> +#include <inttypes.h>

> +

> +#include <test_debug.h>

> +

> +#include <odp_api.h>

> +#include <odp/helper/linux.h>

> +#include <odp/helper/eth.h>

> +#include <odp/helper/ip.h>

> +

> +#include <odp_packet_internal.h>

> +

> +#include "cls_suites.h"

> +

> +/** Get rid of path in filename - only for unix-type paths using '/' */

> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \

> +			    strrchr((file_name), '/') + 1 : (file_name))

> +

> +/**

> + * Print usage information

> + */

> +static void usage(char *progname)

> +{

> +	printf("\n"

> +	       "This is test application to verify that linux-generic classifier\n"

> +	       "correctly classifies packets on input. Main intend is add more code\n"

> +	       "coverage for internal functions playing different traffic recorded to\n"

> +	       "pcap files."

> +	       "\n"

> +	       "Usage: %s OPTIONS\n"

> +	       "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"

> +	       "\n"

> +	       "Mandatory OPTIONS:\n"

> +	       "  -i, pcap file name\n"

> +	       "  -e, expected packet bitmask\n"

> +	       "\n", NO_PATH(progname), NO_PATH(progname)

> +	    );

> +}

> +

> +/** @def SHM_PKT_POOL_SIZE

> + * @brief Size of the shared memory block

> + */

> +#define SHM_PKT_POOL_SIZE      512

> +

> +/** @def SHM_PKT_POOL_BUF_SIZE

> + * @brief Buffer size of the packet pool buffer

> + */

> +#define SHM_PKT_POOL_BUF_SIZE  1856

> +

> +/**

> + * Parsed command line application arguments

> + */

> +typedef struct {

> +	char *file_name;     /**< File name for pcap pktio */

> +	odp_pktio_t pktio;  /**< Pktio dev */

> +	input_flags_t expected_bits; /**< Expected bits from test run */

> +} appl_args_t;

> +

> +/**

> + * Grouping of both parsed CL args and thread specific args - alloc together

> + */

> +typedef struct {

> +	/** Application (parsed) arguments */

> +	appl_args_t appl;

> +} args_t;

> +

> +/** Global pointer to args */

> +static args_t *args;

> +/** Fill this bit struct to check which packet fields were classified */

> +static input_flags_t packet_flags;

> +

> +/**

> + * Parse and store the command line arguments

> + *

> + * @param argc       argument count

> + * @param argv[]     argument vector

> + * @param appl_args  Store application arguments here

> + */

> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args)

> +{

> +	int opt;

> +	int long_index;

> +	static const struct option longopts[] = {

> +		{"interface", required_argument, NULL, 'i'},	/* return 'i' */

> +		{"extected", required_argument, NULL, 'e'},	/* return 'e' */

> +		{"help", no_argument, NULL, 'h'},		/* return 'h' */

> +		{NULL, 0, NULL, 0}

> +	};

> +

> +	static const char *shortopts = ":i:e:h";

> +

> +	/* let helper collect its own arguments (e.g. --odph_proc) */

> +	odph_parse_options(argc, argv, shortopts, longopts);

> +

> +	appl_args->file_name = NULL;

> +	opterr = 0; /* do not issue errors on helper options */

> +	appl_args->expected_bits.all = 0;

> +

> +	while (1) {

> +		opt = getopt_long(argc, argv, shortopts, longopts, &long_index);

> +

> +		if (opt == -1)

> +			break;	/* No more options */

> +

> +		switch (opt) {

> +		case 'i':

> +			appl_args->file_name =  optarg;

> +			break;

> +		case 'e':

> +			appl_args->expected_bits.all = atoll(optarg);

> +			break;

> +

> +		case 'h':

> +			usage(argv[0]);

> +			exit(EXIT_SUCCESS);

> +			break;

> +		default:

> +			break;

> +		}

> +	}

> +

> +	if (!appl_args->file_name) {

> +		usage(argv[0]);

> +		exit(EXIT_SUCCESS);

> +	}

> +

> +	optind = 1;		/* reset 'extern optind' from the getopt lib */

> +}

> +

> +/**

> + * Create a pktio handle and configure in/out queues.

> + *

> + * @param fname Name of device to open

> + * @param pool Pool to associate with device for packet RX/TX

> + *

> + * @return The handle of the created pktio object.

> + * @retval ODP_PKTIO_INVALID if the create fails.

> + */

> +static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)

> +{

> +	odp_pktio_t pktio;

> +	int ret;

> +	odp_pktio_param_t pktio_param;

> +	odp_pktin_queue_param_t pktin_param;

> +	char dev[255];

> +

> +	odp_pktio_param_init(&pktio_param);

> +	pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;

> +

> +	memset(dev, 0, 255);

> +	sprintf(dev, "pcap:in=%s:out=test_out.pcap",  fname);

> +

> +	/* Open a packet IO instance */

> +	pktio = odp_pktio_open(dev, pool, &pktio_param);

> +	if (pktio == ODP_PKTIO_INVALID)

> +		LOG_ABORT("Error: pktio create failed for %s\n", dev);

> +

> +	odp_pktin_queue_param_init(&pktin_param);

> +

> +	pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;

> +

> +	if (odp_pktin_queue_config(pktio, &pktin_param))

> +		LOG_ABORT("Error: pktin config failed for %s\n", dev);

> +

> +	if (odp_pktout_queue_config(pktio, NULL))

> +		LOG_ABORT("Error: pktout config failed for %s\n", dev);

> +

> +	ret = odp_pktio_start(pktio);

> +	if (ret != 0)

> +		LOG_ABORT("Error: unable to start %s\n", dev);

> +

> +	printf("  created pktio:%02" PRIu64

> +	       ", dev:%s, queue mode (ATOMIC queues)\n"

> +	       "  \tdefault pktio%02" PRIu64 "\n",

> +	       odp_pktio_to_u64(pktio), dev,

> +	       odp_pktio_to_u64(pktio));

> +

> +	return pktio;

> +}

> +

> +/**

> + * Packet IO loopback worker thread using ODP queues

> + *

> + * @param arg  thread arguments of type 'thread_args_t *'

> + *

> + * @return 0 on success

> + * @return !0 on any error

> + */

> +static int pktio_queue_thread(void *arg ODP_UNUSED)

> +{

> +	int thr = odp_thread_id();

> +	odp_pktout_queue_t pktout;

> +	odp_packet_t pkt;

> +	odp_event_t ev;

> +	uint64_t sched_wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS * 100);

> +

> +	packet_flags.all = 0;

> +

> +	/* Loop packets */

> +	while (1) {

> +		odp_pktio_t pktio_tmp;

> +

> +		ev = odp_schedule(NULL, sched_wait);

> +		if (ev == ODP_EVENT_INVALID)

> +			break;

> +

> +		pkt = odp_packet_from_event(ev);

> +		if (!odp_packet_is_valid(pkt))

> +			continue;

> +

> +		pktio_tmp = odp_packet_input(pkt);

> +

> +		if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {

> +			LOG_ERR("  [%02i] Error: no pktout queue\n", thr);

> +			return -1;

> +		}

> +

> +		/* Extend bits here for more additional tests */

> +		if (odp_packet_has_l2(pkt))

> +			packet_flags.parsed_l2 = 1;

> +		if (odp_packet_has_vlan(pkt))

> +			packet_flags.vlan = 1;

> +

> +		/* Enqueue the packet for output */

> +		if (odp_pktout_send(pktout, &pkt, 1) != 1) {

> +			LOG_ERR("  [%i] Packet send failed.\n", thr);

> +			odp_packet_free(pkt);

> +			continue;

> +		}

> +	}

> +

> +	return 0;

> +}

> +

> +int cls_main(int argc, char *argv[])

> +{

> +	odph_odpthread_t thread_tbl[1];

> +	odp_pool_t pool;

> +	int num_workers;

> +	int i;

> +	int cpu;

> +	odp_cpumask_t cpumask;

> +	char cpumaskstr[ODP_CPUMASK_STR_SIZE];

> +	odp_pool_param_t params;

> +	odp_instance_t instance;

> +	odph_odpthread_params_t thr_params;

> +

> +	args = calloc(1, sizeof(args_t));

> +	if (args == NULL) {

> +		LOG_ERR("Error: args mem alloc failed.\n");

> +		exit(EXIT_FAILURE);

> +	}

> +

> +	parse_args(argc, argv, &args->appl);

> +

> +	/* Init ODP before calling anything else */

> +	if (odp_init_global(&instance, NULL, NULL)) {

> +		LOG_ERR("Error: ODP global init failed.\n");

> +		exit(EXIT_FAILURE);

> +	}

> +

> +	/* Init this thread */

> +	if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

> +		LOG_ERR("Error: ODP local init failed.\n");

> +		exit(EXIT_FAILURE);

> +	}

> +

> +	num_workers = odp_cpumask_default_worker(&cpumask, 1);

> +	(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));

> +

> +	/* Create packet pool */

> +	odp_pool_param_init(&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_pool", &params);

> +	if (pool == ODP_POOL_INVALID) {

> +		LOG_ERR("Error: packet pool create failed.\n");

> +		exit(EXIT_FAILURE);

> +	}

> +

> +	args->appl.pktio = create_pktio(args->appl.file_name, pool);

> +

> +	/* Create and init worker threads */

> +	memset(thread_tbl, 0, sizeof(thread_tbl));

> +

> +	memset(&thr_params, 0, sizeof(thr_params));

> +	thr_params.thr_type = ODP_THREAD_WORKER;

> +	thr_params.instance = instance;

> +

> +	cpu = odp_cpumask_first(&cpumask);

> +	for (i = 0; i < num_workers; ++i) {

> +		odp_cpumask_t thd_mask;

> +		int (*thr_run_func)(void *);

> +

> +		thr_run_func = pktio_queue_thread;

> +		/*

> +		 * Create threads one-by-one instead of all-at-once,

> +		 * because each thread might get different arguments.

> +		 * Calls odp_thread_create(cpu) for each thread

> +		 */

> +		odp_cpumask_zero(&thd_mask);

> +		odp_cpumask_set(&thd_mask, cpu);

> +

> +		thr_params.start = thr_run_func;

> +		thr_params.arg   = &args;

> +

> +		odph_odpthreads_create(&thread_tbl[i], &thd_mask, &thr_params);

> +		cpu = odp_cpumask_next(&cpumask, cpu);

> +	}

> +

> +	/* Master thread waits for other threads to exit */

> +	for (i = 0; i < num_workers; ++i)

> +		odph_odpthreads_join(&thread_tbl[i]);

> +

> +	odp_pktio_stop(args->appl.pktio);

> +	odp_pktio_close(args->appl.pktio);

> +

> +	while (1) {

> +		odp_event_t ev;

> +

> +		ev = odp_schedule(NULL, 0);

> +		if (ev == ODP_EVENT_INVALID)

> +			break;

> +	}

> +

> +	odp_pool_destroy(pool);

> +	odp_term_local();

> +	odp_term_global(instance);

> +

> +	if (packet_flags.all != args->appl.expected_bits.all) {

> +		LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",

> +			packet_flags.all, args->appl.expected_bits.all);

> +		free(args);

> +		return -1;

> +	}

> +

> +	free(args);

> +	return 0;

> +}

> diff --git a/test/linux-generic/cls/cls_main.c b/test/linux-generic/cls/cls_main.c

> new file mode 100644

> index 0000000..40179b9

> --- /dev/null

> +++ b/test/linux-generic/cls/cls_main.c

> @@ -0,0 +1,12 @@

> +/* Copyright (c) 2016, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include "cls_suites.h"

> +

> +int main(int argc, char *argv[])

> +{

> +	return cls_main(argc, argv);

> +}

> diff --git a/test/linux-generic/cls/cls_suites.h b/test/linux-generic/cls/cls_suites.h

> new file mode 100644

> index 0000000..94c9b55

> --- /dev/null

> +++ b/test/linux-generic/cls/cls_suites.h

> @@ -0,0 +1 @@

> +int cls_main(int argc, char *argv[]);

> diff --git a/test/linux-generic/cls/vlan.pcap b/test/linux-generic/cls/vlan.pcap

> new file mode 100644

> index 0000000000000000000000000000000000000000..106ccb682e51495b4025337518a0bce63c2c7681

> GIT binary patch

> literal 9728

> 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

> H$A|v_$relS

>

> literal 0

> HcmV?d00001

>

> diff --git a/test/linux-generic/cls/vlan_run.sh b/test/linux-generic/cls/vlan_run.sh

> new file mode 100755

> index 0000000..7875eaf

> --- /dev/null

> +++ b/test/linux-generic/cls/vlan_run.sh

> @@ -0,0 +1,49 @@

> +#!/bin/sh

> +#

> +# Copyright (c) 2016, Linaro Limited

> +# All rights reserved.

> +#

> +# SPDX-License-Identifier:      BSD-3-Clause

> +#

> +

> +# directories where binary can be found:

> +# -in the validation dir when running make check (intree or out of tree)

> +# -in the script directory, when running after 'make install', or

> +# -in the validation when running standalone intree,

> +# -in the _build directory, when running after 'make distcheck',

> +# -in the current directory.

> +# running stand alone out of tree requires setting PATH

> +PATH=${TEST_DIR}/linux-generic/cls:$PATH

> +PATH=$(dirname $0):$PATH

> +PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH

> +PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH

> +PATH=.:$PATH

> +

> +bin_path=$(which cls_main${EXEEXT})

> +if [ -x "$bin_path" ] ; then

> +	echo "Running with $bin_path"

> +else

> +	echo "Cannot find cls_main${EXEEXT}"

> +	echo "Please set you PATH for it. PATH=$PATH"

> +fi

> +

> +# Test1: find vlan packets in pcap file and test internal pkt_mmap_vlan_insert()

> +#	 function. Load packets from vlan.pcap file and check that classifier

> +#	 set vlan bits fisible with odp_packet_has_vlan().

> +

> +PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`

> +

> +cls_main -i $PCAP -e 4097

> +ret=$?

> +

> +PCAP_IN_SIZE=`stat -c %s $PCAP`

> +PCAP_OUT_SIZE=`stat -c %s test_out.pcap`

> +

> +rm -f test_out.pcap

> +

> +if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; then

> +	echo "Error: status ${ret}, in:${PCAP_IN_SIZE} out:${PCAP_OUT_SIZE}"

> +	exit 3

> +fi

> +

> +echo "PASS: test 1 passed"

> diff --git a/test/linux-generic/m4/configure.m4 b/test/linux-generic/m4/configure.m4

> index 6b92201..1b722f6 100644

> --- a/test/linux-generic/m4/configure.m4

> +++ b/test/linux-generic/m4/configure.m4

> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

>   AC_CONFIG_FILES([test/linux-generic/Makefile

>   		 test/linux-generic/validation/api/shmem/Makefile

>   		 test/linux-generic/validation/api/pktio/Makefile

> +		 test/linux-generic/cls/Makefile

>   		 test/linux-generic/pktio_ipc/Makefile

>   		 test/linux-generic/ring/Makefile

>   		 test/linux-generic/performance/Makefile])
Mike Holmes Sept. 12, 2016, 3:24 p.m. | #4
On 12 September 2016 at 10:43, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:

> if no comments than it can be merged?



Not without a review, I am interested in this capability but I have not
reviewed it.

I really believe ODP shoudl have as part of the validation the ability to
pass packet streams though and confirm the exact result on the far side,
Krishna ran into this issue with crypto on odp-dpdk which was giving
different results.


>

>

> Maxim.

>

> On 08/29/16 10:50, Maxim Uvarov wrote:

>

>> add pcap play back test which takes 2 arguments: 1 - pcap file,

>> 2 - packet mask to match. Intend is to test odp with different

>> input traffic to check internal implementation functions. In

>> current case it's test for vlan tag instertion for packet mmap:

>> pkt_mmap_vlan_insert().

>>

>> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

>> ---

>>   v3: fix comments noted by Anders

>>

>>   test/linux-generic/.gitignore       |   1 +

>>   test/linux-generic/Makefile.am      |  10 +-

>>   test/linux-generic/cls/.gitignore   |   1 +

>>   test/linux-generic/cls/Makefile.am  |  13 ++

>>   test/linux-generic/cls/cls.c        | 351 ++++++++++++++++++++++++++++++

>> ++++++

>>   test/linux-generic/cls/cls_main.c   |  12 ++

>>   test/linux-generic/cls/cls_suites.h |   1 +

>>   test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes

>>   test/linux-generic/cls/vlan_run.sh  |  49 +++++

>>   test/linux-generic/m4/configure.m4  |   1 +

>>   10 files changed, 435 insertions(+), 4 deletions(-)

>>   create mode 100644 test/linux-generic/cls/.gitignore

>>   create mode 100644 test/linux-generic/cls/Makefile.am

>>   create mode 100644 test/linux-generic/cls/cls.c

>>   create mode 100644 test/linux-generic/cls/cls_main.c

>>   create mode 100644 test/linux-generic/cls/cls_suites.h

>>   create mode 100644 test/linux-generic/cls/vlan.pcap

>>   create mode 100755 test/linux-generic/cls/vlan_run.sh

>>

>> diff --git a/test/linux-generic/.gitignore b/test/linux-generic/.gitignor

>> e

>> index 5dabf91..f65c7c1 100644

>> --- a/test/linux-generic/.gitignore

>> +++ b/test/linux-generic/.gitignore

>> @@ -1,3 +1,4 @@

>>   *.log

>>   *.trs

>>   tests-validation.env

>> +test_out.pcap

>> diff --git a/test/linux-generic/Makefile.am

>> b/test/linux-generic/Makefile.am

>> index 4660cf0..2554f8e 100644

>> --- a/test/linux-generic/Makefile.am

>> +++ b/test/linux-generic/Makefile.am

>> @@ -1,5 +1,8 @@

>>   include $(top_srcdir)/test/Makefile.inc

>>   TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/

>> common_plat/validation

>> +TEST_EXTENSIONS = .sh

>> +

>> +dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>>     ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_pl

>> at/validation/api

>>   @@ -37,11 +40,14 @@ TESTS = validation/api/pktio/pktio_run.sh \

>>     SUBDIRS += validation/api/pktio\

>>            validation/api/shmem\

>> +          cls\

>>            pktio_ipc\

>>            ring

>>     if HAVE_PCAP

>>   TESTS += validation/api/pktio/pktio_run_pcap.sh

>> +TESTS += cls/vlan_run.sh

>> +dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap

>>   endif

>>   if netmap_support

>>   TESTS += validation/api/pktio/pktio_run_netmap.sh

>> @@ -61,10 +67,6 @@ SUBDIRS += validation/api/pktio

>>   endif

>>   endif

>>   -TEST_EXTENSIONS = .sh

>> -

>> -dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>> -

>>   test_SCRIPTS = $(dist_check_SCRIPTS)

>>     tests-validation.env:

>> diff --git a/test/linux-generic/cls/.gitignore

>> b/test/linux-generic/cls/.gitignore

>> new file mode 100644

>> index 0000000..5a652b7

>> --- /dev/null

>> +++ b/test/linux-generic/cls/.gitignore

>> @@ -0,0 +1 @@

>> +cls_main

>> diff --git a/test/linux-generic/cls/Makefile.am

>> b/test/linux-generic/cls/Makefile.am

>> new file mode 100644

>> index 0000000..43fb0bc

>> --- /dev/null

>> +++ b/test/linux-generic/cls/Makefile.am

>> @@ -0,0 +1,13 @@

>> +include ../Makefile.inc

>> +

>> +noinst_LTLIBRARIES = libtestcls.la

>> +libtestcls_la_SOURCES = cls.c

>> +libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)

>> +

>> +test_PROGRAMS = cls_main$(EXEEXT)

>> +dist_cls_main_SOURCES = cls_main.c

>> +

>> +cls_main_LDFLAGS = $(AM_LDFLAGS)

>> +cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)

>> +

>> +noinst_HEADERS = cls_suites.h

>> diff --git a/test/linux-generic/cls/cls.c b/test/linux-generic/cls/cls.c

>> new file mode 100644

>> index 0000000..f6df30a

>> --- /dev/null

>> +++ b/test/linux-generic/cls/cls.c

>> @@ -0,0 +1,351 @@

>> +/* Copyright (c) 2016, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include <stdlib.h>

>> +#include <string.h>

>> +#include <getopt.h>

>> +#include <unistd.h>

>> +#include <inttypes.h>

>> +

>> +#include <test_debug.h>

>> +

>> +#include <odp_api.h>

>> +#include <odp/helper/linux.h>

>> +#include <odp/helper/eth.h>

>> +#include <odp/helper/ip.h>

>> +

>> +#include <odp_packet_internal.h>

>> +

>> +#include "cls_suites.h"

>> +

>> +/** Get rid of path in filename - only for unix-type paths using '/' */

>> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \

>> +                           strrchr((file_name), '/') + 1 : (file_name))

>> +

>> +/**

>> + * Print usage information

>> + */

>> +static void usage(char *progname)

>> +{

>> +       printf("\n"

>> +              "This is test application to verify that linux-generic

>> classifier\n"

>> +              "correctly classifies packets on input. Main intend is add

>> more code\n"

>> +              "coverage for internal functions playing different traffic

>> recorded to\n"

>> +              "pcap files."

>> +              "\n"

>> +              "Usage: %s OPTIONS\n"

>> +              "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"

>> +              "\n"

>> +              "Mandatory OPTIONS:\n"

>> +              "  -i, pcap file name\n"

>> +              "  -e, expected packet bitmask\n"

>> +              "\n", NO_PATH(progname), NO_PATH(progname)

>> +           );

>> +}

>> +

>> +/** @def SHM_PKT_POOL_SIZE

>> + * @brief Size of the shared memory block

>> + */

>> +#define SHM_PKT_POOL_SIZE      512

>> +

>> +/** @def SHM_PKT_POOL_BUF_SIZE

>> + * @brief Buffer size of the packet pool buffer

>> + */

>> +#define SHM_PKT_POOL_BUF_SIZE  1856

>> +

>> +/**

>> + * Parsed command line application arguments

>> + */

>> +typedef struct {

>> +       char *file_name;     /**< File name for pcap pktio */

>> +       odp_pktio_t pktio;  /**< Pktio dev */

>> +       input_flags_t expected_bits; /**< Expected bits from test run */

>> +} appl_args_t;

>> +

>> +/**

>> + * Grouping of both parsed CL args and thread specific args - alloc

>> together

>> + */

>> +typedef struct {

>> +       /** Application (parsed) arguments */

>> +       appl_args_t appl;

>> +} args_t;

>> +

>> +/** Global pointer to args */

>> +static args_t *args;

>> +/** Fill this bit struct to check which packet fields were classified */

>> +static input_flags_t packet_flags;

>> +

>> +/**

>> + * Parse and store the command line arguments

>> + *

>> + * @param argc       argument count

>> + * @param argv[]     argument vector

>> + * @param appl_args  Store application arguments here

>> + */

>> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args)

>> +{

>> +       int opt;

>> +       int long_index;

>> +       static const struct option longopts[] = {

>> +               {"interface", required_argument, NULL, 'i'},    /* return

>> 'i' */

>> +               {"extected", required_argument, NULL, 'e'},     /* return

>> 'e' */

>> +               {"help", no_argument, NULL, 'h'},               /* return

>> 'h' */

>> +               {NULL, 0, NULL, 0}

>> +       };

>> +

>> +       static const char *shortopts = ":i:e:h";

>> +

>> +       /* let helper collect its own arguments (e.g. --odph_proc) */

>> +       odph_parse_options(argc, argv, shortopts, longopts);

>> +

>> +       appl_args->file_name = NULL;

>> +       opterr = 0; /* do not issue errors on helper options */

>> +       appl_args->expected_bits.all = 0;

>> +

>> +       while (1) {

>> +               opt = getopt_long(argc, argv, shortopts, longopts,

>> &long_index);

>> +

>> +               if (opt == -1)

>> +                       break;  /* No more options */

>> +

>> +               switch (opt) {

>> +               case 'i':

>> +                       appl_args->file_name =  optarg;

>> +                       break;

>> +               case 'e':

>> +                       appl_args->expected_bits.all = atoll(optarg);

>> +                       break;

>> +

>> +               case 'h':

>> +                       usage(argv[0]);

>> +                       exit(EXIT_SUCCESS);

>> +                       break;

>> +               default:

>> +                       break;

>> +               }

>> +       }

>> +

>> +       if (!appl_args->file_name) {

>> +               usage(argv[0]);

>> +               exit(EXIT_SUCCESS);

>> +       }

>> +

>> +       optind = 1;             /* reset 'extern optind' from the getopt

>> lib */

>> +}

>> +

>> +/**

>> + * Create a pktio handle and configure in/out queues.

>> + *

>> + * @param fname Name of device to open

>> + * @param pool Pool to associate with device for packet RX/TX

>> + *

>> + * @return The handle of the created pktio object.

>> + * @retval ODP_PKTIO_INVALID if the create fails.

>> + */

>> +static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)

>> +{

>> +       odp_pktio_t pktio;

>> +       int ret;

>> +       odp_pktio_param_t pktio_param;

>> +       odp_pktin_queue_param_t pktin_param;

>> +       char dev[255];

>> +

>> +       odp_pktio_param_init(&pktio_param);

>> +       pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;

>> +

>> +       memset(dev, 0, 255);

>> +       sprintf(dev, "pcap:in=%s:out=test_out.pcap",  fname);

>> +

>> +       /* Open a packet IO instance */

>> +       pktio = odp_pktio_open(dev, pool, &pktio_param);

>> +       if (pktio == ODP_PKTIO_INVALID)

>> +               LOG_ABORT("Error: pktio create failed for %s\n", dev);

>> +

>> +       odp_pktin_queue_param_init(&pktin_param);

>> +

>> +       pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;

>> +

>> +       if (odp_pktin_queue_config(pktio, &pktin_param))

>> +               LOG_ABORT("Error: pktin config failed for %s\n", dev);

>> +

>> +       if (odp_pktout_queue_config(pktio, NULL))

>> +               LOG_ABORT("Error: pktout config failed for %s\n", dev);

>> +

>> +       ret = odp_pktio_start(pktio);

>> +       if (ret != 0)

>> +               LOG_ABORT("Error: unable to start %s\n", dev);

>> +

>> +       printf("  created pktio:%02" PRIu64

>> +              ", dev:%s, queue mode (ATOMIC queues)\n"

>> +              "  \tdefault pktio%02" PRIu64 "\n",

>> +              odp_pktio_to_u64(pktio), dev,

>> +              odp_pktio_to_u64(pktio));

>> +

>> +       return pktio;

>> +}

>> +

>> +/**

>> + * Packet IO loopback worker thread using ODP queues

>> + *

>> + * @param arg  thread arguments of type 'thread_args_t *'

>> + *

>> + * @return 0 on success

>> + * @return !0 on any error

>> + */

>> +static int pktio_queue_thread(void *arg ODP_UNUSED)

>> +{

>> +       int thr = odp_thread_id();

>> +       odp_pktout_queue_t pktout;

>> +       odp_packet_t pkt;

>> +       odp_event_t ev;

>> +       uint64_t sched_wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS

>> * 100);

>> +

>> +       packet_flags.all = 0;

>> +

>> +       /* Loop packets */

>> +       while (1) {

>> +               odp_pktio_t pktio_tmp;

>> +

>> +               ev = odp_schedule(NULL, sched_wait);

>> +               if (ev == ODP_EVENT_INVALID)

>> +                       break;

>> +

>> +               pkt = odp_packet_from_event(ev);

>> +               if (!odp_packet_is_valid(pkt))

>> +                       continue;

>> +

>> +               pktio_tmp = odp_packet_input(pkt);

>> +

>> +               if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {

>> +                       LOG_ERR("  [%02i] Error: no pktout queue\n", thr);

>> +                       return -1;

>> +               }

>> +

>> +               /* Extend bits here for more additional tests */

>> +               if (odp_packet_has_l2(pkt))

>> +                       packet_flags.parsed_l2 = 1;

>> +               if (odp_packet_has_vlan(pkt))

>> +                       packet_flags.vlan = 1;

>> +

>> +               /* Enqueue the packet for output */

>> +               if (odp_pktout_send(pktout, &pkt, 1) != 1) {

>> +                       LOG_ERR("  [%i] Packet send failed.\n", thr);

>> +                       odp_packet_free(pkt);

>> +                       continue;

>> +               }

>> +       }

>> +

>> +       return 0;

>> +}

>> +

>> +int cls_main(int argc, char *argv[])

>> +{

>> +       odph_odpthread_t thread_tbl[1];

>> +       odp_pool_t pool;

>> +       int num_workers;

>> +       int i;

>> +       int cpu;

>> +       odp_cpumask_t cpumask;

>> +       char cpumaskstr[ODP_CPUMASK_STR_SIZE];

>> +       odp_pool_param_t params;

>> +       odp_instance_t instance;

>> +       odph_odpthread_params_t thr_params;

>> +

>> +       args = calloc(1, sizeof(args_t));

>> +       if (args == NULL) {

>> +               LOG_ERR("Error: args mem alloc failed.\n");

>> +               exit(EXIT_FAILURE);

>> +       }

>> +

>> +       parse_args(argc, argv, &args->appl);

>> +

>> +       /* Init ODP before calling anything else */

>> +       if (odp_init_global(&instance, NULL, NULL)) {

>> +               LOG_ERR("Error: ODP global init failed.\n");

>> +               exit(EXIT_FAILURE);

>> +       }

>> +

>> +       /* Init this thread */

>> +       if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

>> +               LOG_ERR("Error: ODP local init failed.\n");

>> +               exit(EXIT_FAILURE);

>> +       }

>> +

>> +       num_workers = odp_cpumask_default_worker(&cpumask, 1);

>> +       (void)odp_cpumask_to_str(&cpumask, cpumaskstr,

>> sizeof(cpumaskstr));

>> +

>> +       /* Create packet pool */

>> +       odp_pool_param_init(&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_pool", &params);

>> +       if (pool == ODP_POOL_INVALID) {

>> +               LOG_ERR("Error: packet pool create failed.\n");

>> +               exit(EXIT_FAILURE);

>> +       }

>> +

>> +       args->appl.pktio = create_pktio(args->appl.file_name, pool);

>> +

>> +       /* Create and init worker threads */

>> +       memset(thread_tbl, 0, sizeof(thread_tbl));

>> +

>> +       memset(&thr_params, 0, sizeof(thr_params));

>> +       thr_params.thr_type = ODP_THREAD_WORKER;

>> +       thr_params.instance = instance;

>> +

>> +       cpu = odp_cpumask_first(&cpumask);

>> +       for (i = 0; i < num_workers; ++i) {

>> +               odp_cpumask_t thd_mask;

>> +               int (*thr_run_func)(void *);

>> +

>> +               thr_run_func = pktio_queue_thread;

>> +               /*

>> +                * Create threads one-by-one instead of all-at-once,

>> +                * because each thread might get different arguments.

>> +                * Calls odp_thread_create(cpu) for each thread

>> +                */

>> +               odp_cpumask_zero(&thd_mask);

>> +               odp_cpumask_set(&thd_mask, cpu);

>> +

>> +               thr_params.start = thr_run_func;

>> +               thr_params.arg   = &args;

>> +

>> +               odph_odpthreads_create(&thread_tbl[i], &thd_mask,

>> &thr_params);

>> +               cpu = odp_cpumask_next(&cpumask, cpu);

>> +       }

>> +

>> +       /* Master thread waits for other threads to exit */

>> +       for (i = 0; i < num_workers; ++i)

>> +               odph_odpthreads_join(&thread_tbl[i]);

>> +

>> +       odp_pktio_stop(args->appl.pktio);

>> +       odp_pktio_close(args->appl.pktio);

>> +

>> +       while (1) {

>> +               odp_event_t ev;

>> +

>> +               ev = odp_schedule(NULL, 0);

>> +               if (ev == ODP_EVENT_INVALID)

>> +                       break;

>> +       }

>> +

>> +       odp_pool_destroy(pool);

>> +       odp_term_local();

>> +       odp_term_global(instance);

>> +

>> +       if (packet_flags.all != args->appl.expected_bits.all) {

>> +               LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",

>> +                       packet_flags.all, args->appl.expected_bits.all);

>> +               free(args);

>> +               return -1;

>> +       }

>> +

>> +       free(args);

>> +       return 0;

>> +}

>> diff --git a/test/linux-generic/cls/cls_main.c

>> b/test/linux-generic/cls/cls_main.c

>> new file mode 100644

>> index 0000000..40179b9

>> --- /dev/null

>> +++ b/test/linux-generic/cls/cls_main.c

>> @@ -0,0 +1,12 @@

>> +/* Copyright (c) 2016, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include "cls_suites.h"

>> +

>> +int main(int argc, char *argv[])

>> +{

>> +       return cls_main(argc, argv);

>> +}

>> diff --git a/test/linux-generic/cls/cls_suites.h

>> b/test/linux-generic/cls/cls_suites.h

>> new file mode 100644

>> index 0000000..94c9b55

>> --- /dev/null

>> +++ b/test/linux-generic/cls/cls_suites.h

>> @@ -0,0 +1 @@

>> +int cls_main(int argc, char *argv[]);

>> diff --git a/test/linux-generic/cls/vlan.pcap

>> b/test/linux-generic/cls/vlan.pcap

>> new file mode 100644

>> index 0000000000000000000000000000000000000000..106ccb682e51495b40

>> 25337518a0bce63c2c7681

>> GIT binary patch

>> literal 9728

>> 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

>> H$A|v_$relS

>>

>> literal 0

>> HcmV?d00001

>>

>> diff --git a/test/linux-generic/cls/vlan_run.sh

>> b/test/linux-generic/cls/vlan_run.sh

>> new file mode 100755

>> index 0000000..7875eaf

>> --- /dev/null

>> +++ b/test/linux-generic/cls/vlan_run.sh

>> @@ -0,0 +1,49 @@

>> +#!/bin/sh

>> +#

>> +# Copyright (c) 2016, Linaro Limited

>> +# All rights reserved.

>> +#

>> +# SPDX-License-Identifier:      BSD-3-Clause

>> +#

>> +

>> +# directories where binary can be found:

>> +# -in the validation dir when running make check (intree or out of tree)

>> +# -in the script directory, when running after 'make install', or

>> +# -in the validation when running standalone intree,

>> +# -in the _build directory, when running after 'make distcheck',

>> +# -in the current directory.

>> +# running stand alone out of tree requires setting PATH

>> +PATH=${TEST_DIR}/linux-generic/cls:$PATH

>> +PATH=$(dirname $0):$PATH

>> +PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH

>> +PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH

>> +PATH=.:$PATH

>> +

>> +bin_path=$(which cls_main${EXEEXT})

>> +if [ -x "$bin_path" ] ; then

>> +       echo "Running with $bin_path"

>> +else

>> +       echo "Cannot find cls_main${EXEEXT}"

>> +       echo "Please set you PATH for it. PATH=$PATH"

>> +fi

>> +

>> +# Test1: find vlan packets in pcap file and test internal

>> pkt_mmap_vlan_insert()

>> +#       function. Load packets from vlan.pcap file and check that

>> classifier

>> +#       set vlan bits fisible with odp_packet_has_vlan().

>> +

>> +PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`

>> +

>> +cls_main -i $PCAP -e 4097

>> +ret=$?

>> +

>> +PCAP_IN_SIZE=`stat -c %s $PCAP`

>> +PCAP_OUT_SIZE=`stat -c %s test_out.pcap`

>> +

>> +rm -f test_out.pcap

>> +

>> +if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; then

>> +       echo "Error: status ${ret}, in:${PCAP_IN_SIZE}

>> out:${PCAP_OUT_SIZE}"

>> +       exit 3

>> +fi

>> +

>> +echo "PASS: test 1 passed"

>> diff --git a/test/linux-generic/m4/configure.m4

>> b/test/linux-generic/m4/configure.m4

>> index 6b92201..1b722f6 100644

>> --- a/test/linux-generic/m4/configure.m4

>> +++ b/test/linux-generic/m4/configure.m4

>> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

>>   AC_CONFIG_FILES([test/linux-generic/Makefile

>>                  test/linux-generic/validation/api/shmem/Makefile

>>                  test/linux-generic/validation/api/pktio/Makefile

>> +                test/linux-generic/cls/Makefile

>>                  test/linux-generic/pktio_ipc/Makefile

>>                  test/linux-generic/ring/Makefile

>>                  test/linux-generic/performance/Makefile])

>>

>

>



-- 
Mike Holmes
Program Manager - Linaro Networking Group
Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
"Work should be fun and collaborative, the rest follows"
Bill Fischofer Sept. 13, 2016, 12:54 a.m. | #5
On Mon, Sep 12, 2016 at 10:24 AM, Mike Holmes <mike.holmes@linaro.org>
wrote:

> On 12 September 2016 at 10:43, Maxim Uvarov <maxim.uvarov@linaro.org>

> wrote:

>

> > if no comments than it can be merged?

>

>

> Not without a review, I am interested in this capability but I have not

> reviewed it.

>


I had previously reviewed and tested v2 of this patch. v3 just incorporates
some additional comments by Anders. If Anders has no objection, my review
can be propagated to v3.


>

> I really believe ODP shoudl have as part of the validation the ability to

> pass packet streams though and confirm the exact result on the far side,

> Krishna ran into this issue with crypto on odp-dpdk which was giving

> different results.

>

>

> >

> >

> > Maxim.

> >

> > On 08/29/16 10:50, Maxim Uvarov wrote:

> >

> >> add pcap play back test which takes 2 arguments: 1 - pcap file,

> >> 2 - packet mask to match. Intend is to test odp with different

> >> input traffic to check internal implementation functions. In

> >> current case it's test for vlan tag instertion for packet mmap:

> >> pkt_mmap_vlan_insert().

> >>

> >> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

> >> ---

> >>   v3: fix comments noted by Anders

> >>

> >>   test/linux-generic/.gitignore       |   1 +

> >>   test/linux-generic/Makefile.am      |  10 +-

> >>   test/linux-generic/cls/.gitignore   |   1 +

> >>   test/linux-generic/cls/Makefile.am  |  13 ++

> >>   test/linux-generic/cls/cls.c        | 351

> ++++++++++++++++++++++++++++++

> >> ++++++

> >>   test/linux-generic/cls/cls_main.c   |  12 ++

> >>   test/linux-generic/cls/cls_suites.h |   1 +

> >>   test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes

> >>   test/linux-generic/cls/vlan_run.sh  |  49 +++++

> >>   test/linux-generic/m4/configure.m4  |   1 +

> >>   10 files changed, 435 insertions(+), 4 deletions(-)

> >>   create mode 100644 test/linux-generic/cls/.gitignore

> >>   create mode 100644 test/linux-generic/cls/Makefile.am

> >>   create mode 100644 test/linux-generic/cls/cls.c

> >>   create mode 100644 test/linux-generic/cls/cls_main.c

> >>   create mode 100644 test/linux-generic/cls/cls_suites.h

> >>   create mode 100644 test/linux-generic/cls/vlan.pcap

> >>   create mode 100755 test/linux-generic/cls/vlan_run.sh

> >>

> >> diff --git a/test/linux-generic/.gitignore

> b/test/linux-generic/.gitignor

> >> e

> >> index 5dabf91..f65c7c1 100644

> >> --- a/test/linux-generic/.gitignore

> >> +++ b/test/linux-generic/.gitignore

> >> @@ -1,3 +1,4 @@

> >>   *.log

> >>   *.trs

> >>   tests-validation.env

> >> +test_out.pcap

> >> diff --git a/test/linux-generic/Makefile.am

> >> b/test/linux-generic/Makefile.am

> >> index 4660cf0..2554f8e 100644

> >> --- a/test/linux-generic/Makefile.am

> >> +++ b/test/linux-generic/Makefile.am

> >> @@ -1,5 +1,8 @@

> >>   include $(top_srcdir)/test/Makefile.inc

> >>   TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/

> >> common_plat/validation

> >> +TEST_EXTENSIONS = .sh

> >> +

> >> +dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

> >>     ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_pl

> >> at/validation/api

> >>   @@ -37,11 +40,14 @@ TESTS = validation/api/pktio/pktio_run.sh \

> >>     SUBDIRS += validation/api/pktio\

> >>            validation/api/shmem\

> >> +          cls\

> >>            pktio_ipc\

> >>            ring

> >>     if HAVE_PCAP

> >>   TESTS += validation/api/pktio/pktio_run_pcap.sh

> >> +TESTS += cls/vlan_run.sh

> >> +dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap

> >>   endif

> >>   if netmap_support

> >>   TESTS += validation/api/pktio/pktio_run_netmap.sh

> >> @@ -61,10 +67,6 @@ SUBDIRS += validation/api/pktio

> >>   endif

> >>   endif

> >>   -TEST_EXTENSIONS = .sh

> >> -

> >> -dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

> >> -

> >>   test_SCRIPTS = $(dist_check_SCRIPTS)

> >>     tests-validation.env:

> >> diff --git a/test/linux-generic/cls/.gitignore

> >> b/test/linux-generic/cls/.gitignore

> >> new file mode 100644

> >> index 0000000..5a652b7

> >> --- /dev/null

> >> +++ b/test/linux-generic/cls/.gitignore

> >> @@ -0,0 +1 @@

> >> +cls_main

> >> diff --git a/test/linux-generic/cls/Makefile.am

> >> b/test/linux-generic/cls/Makefile.am

> >> new file mode 100644

> >> index 0000000..43fb0bc

> >> --- /dev/null

> >> +++ b/test/linux-generic/cls/Makefile.am

> >> @@ -0,0 +1,13 @@

> >> +include ../Makefile.inc

> >> +

> >> +noinst_LTLIBRARIES = libtestcls.la

> >> +libtestcls_la_SOURCES = cls.c

> >> +libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)

> >> +

> >> +test_PROGRAMS = cls_main$(EXEEXT)

> >> +dist_cls_main_SOURCES = cls_main.c

> >> +

> >> +cls_main_LDFLAGS = $(AM_LDFLAGS)

> >> +cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)

> >> +

> >> +noinst_HEADERS = cls_suites.h

> >> diff --git a/test/linux-generic/cls/cls.c b/test/linux-generic/cls/cls.c

> >> new file mode 100644

> >> index 0000000..f6df30a

> >> --- /dev/null

> >> +++ b/test/linux-generic/cls/cls.c

> >> @@ -0,0 +1,351 @@

> >> +/* Copyright (c) 2016, Linaro Limited

> >> + * All rights reserved.

> >> + *

> >> + * SPDX-License-Identifier:     BSD-3-Clause

> >> + */

> >> +

> >> +#include <stdlib.h>

> >> +#include <string.h>

> >> +#include <getopt.h>

> >> +#include <unistd.h>

> >> +#include <inttypes.h>

> >> +

> >> +#include <test_debug.h>

> >> +

> >> +#include <odp_api.h>

> >> +#include <odp/helper/linux.h>

> >> +#include <odp/helper/eth.h>

> >> +#include <odp/helper/ip.h>

> >> +

> >> +#include <odp_packet_internal.h>

> >> +

> >> +#include "cls_suites.h"

> >> +

> >> +/** Get rid of path in filename - only for unix-type paths using '/' */

> >> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \

> >> +                           strrchr((file_name), '/') + 1 : (file_name))

> >> +

> >> +/**

> >> + * Print usage information

> >> + */

> >> +static void usage(char *progname)

> >> +{

> >> +       printf("\n"

> >> +              "This is test application to verify that linux-generic

> >> classifier\n"

> >> +              "correctly classifies packets on input. Main intend is

> add

> >> more code\n"

> >> +              "coverage for internal functions playing different

> traffic

> >> recorded to\n"

> >> +              "pcap files."

> >> +              "\n"

> >> +              "Usage: %s OPTIONS\n"

> >> +              "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"

> >> +              "\n"

> >> +              "Mandatory OPTIONS:\n"

> >> +              "  -i, pcap file name\n"

> >> +              "  -e, expected packet bitmask\n"

> >> +              "\n", NO_PATH(progname), NO_PATH(progname)

> >> +           );

> >> +}

> >> +

> >> +/** @def SHM_PKT_POOL_SIZE

> >> + * @brief Size of the shared memory block

> >> + */

> >> +#define SHM_PKT_POOL_SIZE      512

> >> +

> >> +/** @def SHM_PKT_POOL_BUF_SIZE

> >> + * @brief Buffer size of the packet pool buffer

> >> + */

> >> +#define SHM_PKT_POOL_BUF_SIZE  1856

> >> +

> >> +/**

> >> + * Parsed command line application arguments

> >> + */

> >> +typedef struct {

> >> +       char *file_name;     /**< File name for pcap pktio */

> >> +       odp_pktio_t pktio;  /**< Pktio dev */

> >> +       input_flags_t expected_bits; /**< Expected bits from test run */

> >> +} appl_args_t;

> >> +

> >> +/**

> >> + * Grouping of both parsed CL args and thread specific args - alloc

> >> together

> >> + */

> >> +typedef struct {

> >> +       /** Application (parsed) arguments */

> >> +       appl_args_t appl;

> >> +} args_t;

> >> +

> >> +/** Global pointer to args */

> >> +static args_t *args;

> >> +/** Fill this bit struct to check which packet fields were classified

> */

> >> +static input_flags_t packet_flags;

> >> +

> >> +/**

> >> + * Parse and store the command line arguments

> >> + *

> >> + * @param argc       argument count

> >> + * @param argv[]     argument vector

> >> + * @param appl_args  Store application arguments here

> >> + */

> >> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args)

> >> +{

> >> +       int opt;

> >> +       int long_index;

> >> +       static const struct option longopts[] = {

> >> +               {"interface", required_argument, NULL, 'i'},    /*

> return

> >> 'i' */

> >> +               {"extected", required_argument, NULL, 'e'},     /*

> return

> >> 'e' */

> >> +               {"help", no_argument, NULL, 'h'},               /*

> return

> >> 'h' */

> >> +               {NULL, 0, NULL, 0}

> >> +       };

> >> +

> >> +       static const char *shortopts = ":i:e:h";

> >> +

> >> +       /* let helper collect its own arguments (e.g. --odph_proc) */

> >> +       odph_parse_options(argc, argv, shortopts, longopts);

> >> +

> >> +       appl_args->file_name = NULL;

> >> +       opterr = 0; /* do not issue errors on helper options */

> >> +       appl_args->expected_bits.all = 0;

> >> +

> >> +       while (1) {

> >> +               opt = getopt_long(argc, argv, shortopts, longopts,

> >> &long_index);

> >> +

> >> +               if (opt == -1)

> >> +                       break;  /* No more options */

> >> +

> >> +               switch (opt) {

> >> +               case 'i':

> >> +                       appl_args->file_name =  optarg;

> >> +                       break;

> >> +               case 'e':

> >> +                       appl_args->expected_bits.all = atoll(optarg);

> >> +                       break;

> >> +

> >> +               case 'h':

> >> +                       usage(argv[0]);

> >> +                       exit(EXIT_SUCCESS);

> >> +                       break;

> >> +               default:

> >> +                       break;

> >> +               }

> >> +       }

> >> +

> >> +       if (!appl_args->file_name) {

> >> +               usage(argv[0]);

> >> +               exit(EXIT_SUCCESS);

> >> +       }

> >> +

> >> +       optind = 1;             /* reset 'extern optind' from the getopt

> >> lib */

> >> +}

> >> +

> >> +/**

> >> + * Create a pktio handle and configure in/out queues.

> >> + *

> >> + * @param fname Name of device to open

> >> + * @param pool Pool to associate with device for packet RX/TX

> >> + *

> >> + * @return The handle of the created pktio object.

> >> + * @retval ODP_PKTIO_INVALID if the create fails.

> >> + */

> >> +static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)

> >> +{

> >> +       odp_pktio_t pktio;

> >> +       int ret;

> >> +       odp_pktio_param_t pktio_param;

> >> +       odp_pktin_queue_param_t pktin_param;

> >> +       char dev[255];

> >> +

> >> +       odp_pktio_param_init(&pktio_param);

> >> +       pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;

> >> +

> >> +       memset(dev, 0, 255);

> >> +       sprintf(dev, "pcap:in=%s:out=test_out.pcap",  fname);

> >> +

> >> +       /* Open a packet IO instance */

> >> +       pktio = odp_pktio_open(dev, pool, &pktio_param);

> >> +       if (pktio == ODP_PKTIO_INVALID)

> >> +               LOG_ABORT("Error: pktio create failed for %s\n", dev);

> >> +

> >> +       odp_pktin_queue_param_init(&pktin_param);

> >> +

> >> +       pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;

> >> +

> >> +       if (odp_pktin_queue_config(pktio, &pktin_param))

> >> +               LOG_ABORT("Error: pktin config failed for %s\n", dev);

> >> +

> >> +       if (odp_pktout_queue_config(pktio, NULL))

> >> +               LOG_ABORT("Error: pktout config failed for %s\n", dev);

> >> +

> >> +       ret = odp_pktio_start(pktio);

> >> +       if (ret != 0)

> >> +               LOG_ABORT("Error: unable to start %s\n", dev);

> >> +

> >> +       printf("  created pktio:%02" PRIu64

> >> +              ", dev:%s, queue mode (ATOMIC queues)\n"

> >> +              "  \tdefault pktio%02" PRIu64 "\n",

> >> +              odp_pktio_to_u64(pktio), dev,

> >> +              odp_pktio_to_u64(pktio));

> >> +

> >> +       return pktio;

> >> +}

> >> +

> >> +/**

> >> + * Packet IO loopback worker thread using ODP queues

> >> + *

> >> + * @param arg  thread arguments of type 'thread_args_t *'

> >> + *

> >> + * @return 0 on success

> >> + * @return !0 on any error

> >> + */

> >> +static int pktio_queue_thread(void *arg ODP_UNUSED)

> >> +{

> >> +       int thr = odp_thread_id();

> >> +       odp_pktout_queue_t pktout;

> >> +       odp_packet_t pkt;

> >> +       odp_event_t ev;

> >> +       uint64_t sched_wait = odp_schedule_wait_time(ODP_

> TIME_MSEC_IN_NS

> >> * 100);

> >> +

> >> +       packet_flags.all = 0;

> >> +

> >> +       /* Loop packets */

> >> +       while (1) {

> >> +               odp_pktio_t pktio_tmp;

> >> +

> >> +               ev = odp_schedule(NULL, sched_wait);

> >> +               if (ev == ODP_EVENT_INVALID)

> >> +                       break;

> >> +

> >> +               pkt = odp_packet_from_event(ev);

> >> +               if (!odp_packet_is_valid(pkt))

> >> +                       continue;

> >> +

> >> +               pktio_tmp = odp_packet_input(pkt);

> >> +

> >> +               if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {

> >> +                       LOG_ERR("  [%02i] Error: no pktout queue\n",

> thr);

> >> +                       return -1;

> >> +               }

> >> +

> >> +               /* Extend bits here for more additional tests */

> >> +               if (odp_packet_has_l2(pkt))

> >> +                       packet_flags.parsed_l2 = 1;

> >> +               if (odp_packet_has_vlan(pkt))

> >> +                       packet_flags.vlan = 1;

> >> +

> >> +               /* Enqueue the packet for output */

> >> +               if (odp_pktout_send(pktout, &pkt, 1) != 1) {

> >> +                       LOG_ERR("  [%i] Packet send failed.\n", thr);

> >> +                       odp_packet_free(pkt);

> >> +                       continue;

> >> +               }

> >> +       }

> >> +

> >> +       return 0;

> >> +}

> >> +

> >> +int cls_main(int argc, char *argv[])

> >> +{

> >> +       odph_odpthread_t thread_tbl[1];

> >> +       odp_pool_t pool;

> >> +       int num_workers;

> >> +       int i;

> >> +       int cpu;

> >> +       odp_cpumask_t cpumask;

> >> +       char cpumaskstr[ODP_CPUMASK_STR_SIZE];

> >> +       odp_pool_param_t params;

> >> +       odp_instance_t instance;

> >> +       odph_odpthread_params_t thr_params;

> >> +

> >> +       args = calloc(1, sizeof(args_t));

> >> +       if (args == NULL) {

> >> +               LOG_ERR("Error: args mem alloc failed.\n");

> >> +               exit(EXIT_FAILURE);

> >> +       }

> >> +

> >> +       parse_args(argc, argv, &args->appl);

> >> +

> >> +       /* Init ODP before calling anything else */

> >> +       if (odp_init_global(&instance, NULL, NULL)) {

> >> +               LOG_ERR("Error: ODP global init failed.\n");

> >> +               exit(EXIT_FAILURE);

> >> +       }

> >> +

> >> +       /* Init this thread */

> >> +       if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

> >> +               LOG_ERR("Error: ODP local init failed.\n");

> >> +               exit(EXIT_FAILURE);

> >> +       }

> >> +

> >> +       num_workers = odp_cpumask_default_worker(&cpumask, 1);

> >> +       (void)odp_cpumask_to_str(&cpumask, cpumaskstr,

> >> sizeof(cpumaskstr));

> >> +

> >> +       /* Create packet pool */

> >> +       odp_pool_param_init(&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_pool", &params);

> >> +       if (pool == ODP_POOL_INVALID) {

> >> +               LOG_ERR("Error: packet pool create failed.\n");

> >> +               exit(EXIT_FAILURE);

> >> +       }

> >> +

> >> +       args->appl.pktio = create_pktio(args->appl.file_name, pool);

> >> +

> >> +       /* Create and init worker threads */

> >> +       memset(thread_tbl, 0, sizeof(thread_tbl));

> >> +

> >> +       memset(&thr_params, 0, sizeof(thr_params));

> >> +       thr_params.thr_type = ODP_THREAD_WORKER;

> >> +       thr_params.instance = instance;

> >> +

> >> +       cpu = odp_cpumask_first(&cpumask);

> >> +       for (i = 0; i < num_workers; ++i) {

> >> +               odp_cpumask_t thd_mask;

> >> +               int (*thr_run_func)(void *);

> >> +

> >> +               thr_run_func = pktio_queue_thread;

> >> +               /*

> >> +                * Create threads one-by-one instead of all-at-once,

> >> +                * because each thread might get different arguments.

> >> +                * Calls odp_thread_create(cpu) for each thread

> >> +                */

> >> +               odp_cpumask_zero(&thd_mask);

> >> +               odp_cpumask_set(&thd_mask, cpu);

> >> +

> >> +               thr_params.start = thr_run_func;

> >> +               thr_params.arg   = &args;

> >> +

> >> +               odph_odpthreads_create(&thread_tbl[i], &thd_mask,

> >> &thr_params);

> >> +               cpu = odp_cpumask_next(&cpumask, cpu);

> >> +       }

> >> +

> >> +       /* Master thread waits for other threads to exit */

> >> +       for (i = 0; i < num_workers; ++i)

> >> +               odph_odpthreads_join(&thread_tbl[i]);

> >> +

> >> +       odp_pktio_stop(args->appl.pktio);

> >> +       odp_pktio_close(args->appl.pktio);

> >> +

> >> +       while (1) {

> >> +               odp_event_t ev;

> >> +

> >> +               ev = odp_schedule(NULL, 0);

> >> +               if (ev == ODP_EVENT_INVALID)

> >> +                       break;

> >> +       }

> >> +

> >> +       odp_pool_destroy(pool);

> >> +       odp_term_local();

> >> +       odp_term_global(instance);

> >> +

> >> +       if (packet_flags.all != args->appl.expected_bits.all) {

> >> +               LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",

> >> +                       packet_flags.all, args->appl.expected_bits.all);

> >> +               free(args);

> >> +               return -1;

> >> +       }

> >> +

> >> +       free(args);

> >> +       return 0;

> >> +}

> >> diff --git a/test/linux-generic/cls/cls_main.c

> >> b/test/linux-generic/cls/cls_main.c

> >> new file mode 100644

> >> index 0000000..40179b9

> >> --- /dev/null

> >> +++ b/test/linux-generic/cls/cls_main.c

> >> @@ -0,0 +1,12 @@

> >> +/* Copyright (c) 2016, Linaro Limited

> >> + * All rights reserved.

> >> + *

> >> + * SPDX-License-Identifier:     BSD-3-Clause

> >> + */

> >> +

> >> +#include "cls_suites.h"

> >> +

> >> +int main(int argc, char *argv[])

> >> +{

> >> +       return cls_main(argc, argv);

> >> +}

> >> diff --git a/test/linux-generic/cls/cls_suites.h

> >> b/test/linux-generic/cls/cls_suites.h

> >> new file mode 100644

> >> index 0000000..94c9b55

> >> --- /dev/null

> >> +++ b/test/linux-generic/cls/cls_suites.h

> >> @@ -0,0 +1 @@

> >> +int cls_main(int argc, char *argv[]);

> >> diff --git a/test/linux-generic/cls/vlan.pcap

> >> b/test/linux-generic/cls/vlan.pcap

> >> new file mode 100644

> >> index 0000000000000000000000000000000000000000..106ccb682e51495b40

> >> 25337518a0bce63c2c7681

> >> GIT binary patch

> >> literal 9728

> >> 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

> >> H$A|v_$relS

> >>

> >> literal 0

> >> HcmV?d00001

> >>

> >> diff --git a/test/linux-generic/cls/vlan_run.sh

> >> b/test/linux-generic/cls/vlan_run.sh

> >> new file mode 100755

> >> index 0000000..7875eaf

> >> --- /dev/null

> >> +++ b/test/linux-generic/cls/vlan_run.sh

> >> @@ -0,0 +1,49 @@

> >> +#!/bin/sh

> >> +#

> >> +# Copyright (c) 2016, Linaro Limited

> >> +# All rights reserved.

> >> +#

> >> +# SPDX-License-Identifier:      BSD-3-Clause

> >> +#

> >> +

> >> +# directories where binary can be found:

> >> +# -in the validation dir when running make check (intree or out of

> tree)

> >> +# -in the script directory, when running after 'make install', or

> >> +# -in the validation when running standalone intree,

> >> +# -in the _build directory, when running after 'make distcheck',

> >> +# -in the current directory.

> >> +# running stand alone out of tree requires setting PATH

> >> +PATH=${TEST_DIR}/linux-generic/cls:$PATH

> >> +PATH=$(dirname $0):$PATH

> >> +PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH

> >> +PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH

> >> +PATH=.:$PATH

> >> +

> >> +bin_path=$(which cls_main${EXEEXT})

> >> +if [ -x "$bin_path" ] ; then

> >> +       echo "Running with $bin_path"

> >> +else

> >> +       echo "Cannot find cls_main${EXEEXT}"

> >> +       echo "Please set you PATH for it. PATH=$PATH"

> >> +fi

> >> +

> >> +# Test1: find vlan packets in pcap file and test internal

> >> pkt_mmap_vlan_insert()

> >> +#       function. Load packets from vlan.pcap file and check that

> >> classifier

> >> +#       set vlan bits fisible with odp_packet_has_vlan().

> >> +

> >> +PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`

> >> +

> >> +cls_main -i $PCAP -e 4097

> >> +ret=$?

> >> +

> >> +PCAP_IN_SIZE=`stat -c %s $PCAP`

> >> +PCAP_OUT_SIZE=`stat -c %s test_out.pcap`

> >> +

> >> +rm -f test_out.pcap

> >> +

> >> +if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; then

> >> +       echo "Error: status ${ret}, in:${PCAP_IN_SIZE}

> >> out:${PCAP_OUT_SIZE}"

> >> +       exit 3

> >> +fi

> >> +

> >> +echo "PASS: test 1 passed"

> >> diff --git a/test/linux-generic/m4/configure.m4

> >> b/test/linux-generic/m4/configure.m4

> >> index 6b92201..1b722f6 100644

> >> --- a/test/linux-generic/m4/configure.m4

> >> +++ b/test/linux-generic/m4/configure.m4

> >> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

> >>   AC_CONFIG_FILES([test/linux-generic/Makefile

> >>                  test/linux-generic/validation/api/shmem/Makefile

> >>                  test/linux-generic/validation/api/pktio/Makefile

> >> +                test/linux-generic/cls/Makefile

> >>                  test/linux-generic/pktio_ipc/Makefile

> >>                  test/linux-generic/ring/Makefile

> >>                  test/linux-generic/performance/Makefile])

> >>

> >

> >

>

>

> --

> Mike Holmes

> Program Manager - Linaro Networking Group

> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs

> "Work should be fun and collaborative, the rest follows"

>
Anders Roxell Sept. 14, 2016, 6:45 p.m. | #6
On 2016-09-12 19:54, Bill Fischofer wrote:
> On Mon, Sep 12, 2016 at 10:24 AM, Mike Holmes <mike.holmes@linaro.org>

> wrote:

> 

> > On 12 September 2016 at 10:43, Maxim Uvarov <maxim.uvarov@linaro.org>

> > wrote:

> >

> > > if no comments than it can be merged?

> >

> >

> > Not without a review, I am interested in this capability but I have not

> > reviewed it.

> >

> 

> I had previously reviewed and tested v2 of this patch. v3 just incorporates

> some additional comments by Anders. If Anders has no objection, my review

> can be propagated to v3.


I don't think we resolved this issue raised [1], and you (Bill) had a
comment about not screwing up performance while tinkering with it [2].

Cheers,
Anders
[1] https://lists.linaro.org/pipermail/lng-odp/2016-August/025421.html
[2] https://lists.linaro.org/pipermail/lng-odp/2016-August/025407.html

> 

> 

> >

> > I really believe ODP shoudl have as part of the validation the ability to

> > pass packet streams though and confirm the exact result on the far side,

> > Krishna ran into this issue with crypto on odp-dpdk which was giving

> > different results.

> >

> >

> > >

> > >

> > > Maxim.

> > >

> > > On 08/29/16 10:50, Maxim Uvarov wrote:

> > >

> > >> add pcap play back test which takes 2 arguments: 1 - pcap file,

> > >> 2 - packet mask to match. Intend is to test odp with different

> > >> input traffic to check internal implementation functions. In

> > >> current case it's test for vlan tag instertion for packet mmap:

> > >> pkt_mmap_vlan_insert().

> > >>

> > >> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

> > >> ---

> > >>   v3: fix comments noted by Anders

> > >>

> > >>   test/linux-generic/.gitignore       |   1 +

> > >>   test/linux-generic/Makefile.am      |  10 +-

> > >>   test/linux-generic/cls/.gitignore   |   1 +

> > >>   test/linux-generic/cls/Makefile.am  |  13 ++

> > >>   test/linux-generic/cls/cls.c        | 351

> > ++++++++++++++++++++++++++++++

> > >> ++++++

> > >>   test/linux-generic/cls/cls_main.c   |  12 ++

> > >>   test/linux-generic/cls/cls_suites.h |   1 +

> > >>   test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes

> > >>   test/linux-generic/cls/vlan_run.sh  |  49 +++++

> > >>   test/linux-generic/m4/configure.m4  |   1 +

> > >>   10 files changed, 435 insertions(+), 4 deletions(-)

> > >>   create mode 100644 test/linux-generic/cls/.gitignore

> > >>   create mode 100644 test/linux-generic/cls/Makefile.am

> > >>   create mode 100644 test/linux-generic/cls/cls.c

> > >>   create mode 100644 test/linux-generic/cls/cls_main.c

> > >>   create mode 100644 test/linux-generic/cls/cls_suites.h

> > >>   create mode 100644 test/linux-generic/cls/vlan.pcap

> > >>   create mode 100755 test/linux-generic/cls/vlan_run.sh

> > >>

> > >> diff --git a/test/linux-generic/.gitignore

> > b/test/linux-generic/.gitignor

> > >> e

> > >> index 5dabf91..f65c7c1 100644

> > >> --- a/test/linux-generic/.gitignore

> > >> +++ b/test/linux-generic/.gitignore

> > >> @@ -1,3 +1,4 @@

> > >>   *.log

> > >>   *.trs

> > >>   tests-validation.env

> > >> +test_out.pcap

> > >> diff --git a/test/linux-generic/Makefile.am

> > >> b/test/linux-generic/Makefile.am

> > >> index 4660cf0..2554f8e 100644

> > >> --- a/test/linux-generic/Makefile.am

> > >> +++ b/test/linux-generic/Makefile.am

> > >> @@ -1,5 +1,8 @@

> > >>   include $(top_srcdir)/test/Makefile.inc

> > >>   TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/

> > >> common_plat/validation

> > >> +TEST_EXTENSIONS = .sh

> > >> +

> > >> +dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

> > >>     ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_pl

> > >> at/validation/api

> > >>   @@ -37,11 +40,14 @@ TESTS = validation/api/pktio/pktio_run.sh \

> > >>     SUBDIRS += validation/api/pktio\

> > >>            validation/api/shmem\

> > >> +          cls\

> > >>            pktio_ipc\

> > >>            ring

> > >>     if HAVE_PCAP

> > >>   TESTS += validation/api/pktio/pktio_run_pcap.sh

> > >> +TESTS += cls/vlan_run.sh

> > >> +dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap

> > >>   endif

> > >>   if netmap_support

> > >>   TESTS += validation/api/pktio/pktio_run_netmap.sh

> > >> @@ -61,10 +67,6 @@ SUBDIRS += validation/api/pktio

> > >>   endif

> > >>   endif

> > >>   -TEST_EXTENSIONS = .sh

> > >> -

> > >> -dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

> > >> -

> > >>   test_SCRIPTS = $(dist_check_SCRIPTS)

> > >>     tests-validation.env:

> > >> diff --git a/test/linux-generic/cls/.gitignore

> > >> b/test/linux-generic/cls/.gitignore

> > >> new file mode 100644

> > >> index 0000000..5a652b7

> > >> --- /dev/null

> > >> +++ b/test/linux-generic/cls/.gitignore

> > >> @@ -0,0 +1 @@

> > >> +cls_main

> > >> diff --git a/test/linux-generic/cls/Makefile.am

> > >> b/test/linux-generic/cls/Makefile.am

> > >> new file mode 100644

> > >> index 0000000..43fb0bc

> > >> --- /dev/null

> > >> +++ b/test/linux-generic/cls/Makefile.am

> > >> @@ -0,0 +1,13 @@

> > >> +include ../Makefile.inc

> > >> +

> > >> +noinst_LTLIBRARIES = libtestcls.la

> > >> +libtestcls_la_SOURCES = cls.c

> > >> +libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)

> > >> +

> > >> +test_PROGRAMS = cls_main$(EXEEXT)

> > >> +dist_cls_main_SOURCES = cls_main.c

> > >> +

> > >> +cls_main_LDFLAGS = $(AM_LDFLAGS)

> > >> +cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)

> > >> +

> > >> +noinst_HEADERS = cls_suites.h

> > >> diff --git a/test/linux-generic/cls/cls.c b/test/linux-generic/cls/cls.c

> > >> new file mode 100644

> > >> index 0000000..f6df30a

> > >> --- /dev/null

> > >> +++ b/test/linux-generic/cls/cls.c

> > >> @@ -0,0 +1,351 @@

> > >> +/* Copyright (c) 2016, Linaro Limited

> > >> + * All rights reserved.

> > >> + *

> > >> + * SPDX-License-Identifier:     BSD-3-Clause

> > >> + */

> > >> +

> > >> +#include <stdlib.h>

> > >> +#include <string.h>

> > >> +#include <getopt.h>

> > >> +#include <unistd.h>

> > >> +#include <inttypes.h>

> > >> +

> > >> +#include <test_debug.h>

> > >> +

> > >> +#include <odp_api.h>

> > >> +#include <odp/helper/linux.h>

> > >> +#include <odp/helper/eth.h>

> > >> +#include <odp/helper/ip.h>

> > >> +

> > >> +#include <odp_packet_internal.h>

> > >> +

> > >> +#include "cls_suites.h"

> > >> +

> > >> +/** Get rid of path in filename - only for unix-type paths using '/' */

> > >> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \

> > >> +                           strrchr((file_name), '/') + 1 : (file_name))

> > >> +

> > >> +/**

> > >> + * Print usage information

> > >> + */

> > >> +static void usage(char *progname)

> > >> +{

> > >> +       printf("\n"

> > >> +              "This is test application to verify that linux-generic

> > >> classifier\n"

> > >> +              "correctly classifies packets on input. Main intend is

> > add

> > >> more code\n"

> > >> +              "coverage for internal functions playing different

> > traffic

> > >> recorded to\n"

> > >> +              "pcap files."

> > >> +              "\n"

> > >> +              "Usage: %s OPTIONS\n"

> > >> +              "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"

> > >> +              "\n"

> > >> +              "Mandatory OPTIONS:\n"

> > >> +              "  -i, pcap file name\n"

> > >> +              "  -e, expected packet bitmask\n"

> > >> +              "\n", NO_PATH(progname), NO_PATH(progname)

> > >> +           );

> > >> +}

> > >> +

> > >> +/** @def SHM_PKT_POOL_SIZE

> > >> + * @brief Size of the shared memory block

> > >> + */

> > >> +#define SHM_PKT_POOL_SIZE      512

> > >> +

> > >> +/** @def SHM_PKT_POOL_BUF_SIZE

> > >> + * @brief Buffer size of the packet pool buffer

> > >> + */

> > >> +#define SHM_PKT_POOL_BUF_SIZE  1856

> > >> +

> > >> +/**

> > >> + * Parsed command line application arguments

> > >> + */

> > >> +typedef struct {

> > >> +       char *file_name;     /**< File name for pcap pktio */

> > >> +       odp_pktio_t pktio;  /**< Pktio dev */

> > >> +       input_flags_t expected_bits; /**< Expected bits from test run */

> > >> +} appl_args_t;

> > >> +

> > >> +/**

> > >> + * Grouping of both parsed CL args and thread specific args - alloc

> > >> together

> > >> + */

> > >> +typedef struct {

> > >> +       /** Application (parsed) arguments */

> > >> +       appl_args_t appl;

> > >> +} args_t;

> > >> +

> > >> +/** Global pointer to args */

> > >> +static args_t *args;

> > >> +/** Fill this bit struct to check which packet fields were classified

> > */

> > >> +static input_flags_t packet_flags;

> > >> +

> > >> +/**

> > >> + * Parse and store the command line arguments

> > >> + *

> > >> + * @param argc       argument count

> > >> + * @param argv[]     argument vector

> > >> + * @param appl_args  Store application arguments here

> > >> + */

> > >> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args)

> > >> +{

> > >> +       int opt;

> > >> +       int long_index;

> > >> +       static const struct option longopts[] = {

> > >> +               {"interface", required_argument, NULL, 'i'},    /*

> > return

> > >> 'i' */

> > >> +               {"extected", required_argument, NULL, 'e'},     /*

> > return

> > >> 'e' */

> > >> +               {"help", no_argument, NULL, 'h'},               /*

> > return

> > >> 'h' */

> > >> +               {NULL, 0, NULL, 0}

> > >> +       };

> > >> +

> > >> +       static const char *shortopts = ":i:e:h";

> > >> +

> > >> +       /* let helper collect its own arguments (e.g. --odph_proc) */

> > >> +       odph_parse_options(argc, argv, shortopts, longopts);

> > >> +

> > >> +       appl_args->file_name = NULL;

> > >> +       opterr = 0; /* do not issue errors on helper options */

> > >> +       appl_args->expected_bits.all = 0;

> > >> +

> > >> +       while (1) {

> > >> +               opt = getopt_long(argc, argv, shortopts, longopts,

> > >> &long_index);

> > >> +

> > >> +               if (opt == -1)

> > >> +                       break;  /* No more options */

> > >> +

> > >> +               switch (opt) {

> > >> +               case 'i':

> > >> +                       appl_args->file_name =  optarg;

> > >> +                       break;

> > >> +               case 'e':

> > >> +                       appl_args->expected_bits.all = atoll(optarg);

> > >> +                       break;

> > >> +

> > >> +               case 'h':

> > >> +                       usage(argv[0]);

> > >> +                       exit(EXIT_SUCCESS);

> > >> +                       break;

> > >> +               default:

> > >> +                       break;

> > >> +               }

> > >> +       }

> > >> +

> > >> +       if (!appl_args->file_name) {

> > >> +               usage(argv[0]);

> > >> +               exit(EXIT_SUCCESS);

> > >> +       }

> > >> +

> > >> +       optind = 1;             /* reset 'extern optind' from the getopt

> > >> lib */

> > >> +}

> > >> +

> > >> +/**

> > >> + * Create a pktio handle and configure in/out queues.

> > >> + *

> > >> + * @param fname Name of device to open

> > >> + * @param pool Pool to associate with device for packet RX/TX

> > >> + *

> > >> + * @return The handle of the created pktio object.

> > >> + * @retval ODP_PKTIO_INVALID if the create fails.

> > >> + */

> > >> +static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)

> > >> +{

> > >> +       odp_pktio_t pktio;

> > >> +       int ret;

> > >> +       odp_pktio_param_t pktio_param;

> > >> +       odp_pktin_queue_param_t pktin_param;

> > >> +       char dev[255];

> > >> +

> > >> +       odp_pktio_param_init(&pktio_param);

> > >> +       pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;

> > >> +

> > >> +       memset(dev, 0, 255);

> > >> +       sprintf(dev, "pcap:in=%s:out=test_out.pcap",  fname);

> > >> +

> > >> +       /* Open a packet IO instance */

> > >> +       pktio = odp_pktio_open(dev, pool, &pktio_param);

> > >> +       if (pktio == ODP_PKTIO_INVALID)

> > >> +               LOG_ABORT("Error: pktio create failed for %s\n", dev);

> > >> +

> > >> +       odp_pktin_queue_param_init(&pktin_param);

> > >> +

> > >> +       pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;

> > >> +

> > >> +       if (odp_pktin_queue_config(pktio, &pktin_param))

> > >> +               LOG_ABORT("Error: pktin config failed for %s\n", dev);

> > >> +

> > >> +       if (odp_pktout_queue_config(pktio, NULL))

> > >> +               LOG_ABORT("Error: pktout config failed for %s\n", dev);

> > >> +

> > >> +       ret = odp_pktio_start(pktio);

> > >> +       if (ret != 0)

> > >> +               LOG_ABORT("Error: unable to start %s\n", dev);

> > >> +

> > >> +       printf("  created pktio:%02" PRIu64

> > >> +              ", dev:%s, queue mode (ATOMIC queues)\n"

> > >> +              "  \tdefault pktio%02" PRIu64 "\n",

> > >> +              odp_pktio_to_u64(pktio), dev,

> > >> +              odp_pktio_to_u64(pktio));

> > >> +

> > >> +       return pktio;

> > >> +}

> > >> +

> > >> +/**

> > >> + * Packet IO loopback worker thread using ODP queues

> > >> + *

> > >> + * @param arg  thread arguments of type 'thread_args_t *'

> > >> + *

> > >> + * @return 0 on success

> > >> + * @return !0 on any error

> > >> + */

> > >> +static int pktio_queue_thread(void *arg ODP_UNUSED)

> > >> +{

> > >> +       int thr = odp_thread_id();

> > >> +       odp_pktout_queue_t pktout;

> > >> +       odp_packet_t pkt;

> > >> +       odp_event_t ev;

> > >> +       uint64_t sched_wait = odp_schedule_wait_time(ODP_

> > TIME_MSEC_IN_NS

> > >> * 100);

> > >> +

> > >> +       packet_flags.all = 0;

> > >> +

> > >> +       /* Loop packets */

> > >> +       while (1) {

> > >> +               odp_pktio_t pktio_tmp;

> > >> +

> > >> +               ev = odp_schedule(NULL, sched_wait);

> > >> +               if (ev == ODP_EVENT_INVALID)

> > >> +                       break;

> > >> +

> > >> +               pkt = odp_packet_from_event(ev);

> > >> +               if (!odp_packet_is_valid(pkt))

> > >> +                       continue;

> > >> +

> > >> +               pktio_tmp = odp_packet_input(pkt);

> > >> +

> > >> +               if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {

> > >> +                       LOG_ERR("  [%02i] Error: no pktout queue\n",

> > thr);

> > >> +                       return -1;

> > >> +               }

> > >> +

> > >> +               /* Extend bits here for more additional tests */

> > >> +               if (odp_packet_has_l2(pkt))

> > >> +                       packet_flags.parsed_l2 = 1;

> > >> +               if (odp_packet_has_vlan(pkt))

> > >> +                       packet_flags.vlan = 1;

> > >> +

> > >> +               /* Enqueue the packet for output */

> > >> +               if (odp_pktout_send(pktout, &pkt, 1) != 1) {

> > >> +                       LOG_ERR("  [%i] Packet send failed.\n", thr);

> > >> +                       odp_packet_free(pkt);

> > >> +                       continue;

> > >> +               }

> > >> +       }

> > >> +

> > >> +       return 0;

> > >> +}

> > >> +

> > >> +int cls_main(int argc, char *argv[])

> > >> +{

> > >> +       odph_odpthread_t thread_tbl[1];

> > >> +       odp_pool_t pool;

> > >> +       int num_workers;

> > >> +       int i;

> > >> +       int cpu;

> > >> +       odp_cpumask_t cpumask;

> > >> +       char cpumaskstr[ODP_CPUMASK_STR_SIZE];

> > >> +       odp_pool_param_t params;

> > >> +       odp_instance_t instance;

> > >> +       odph_odpthread_params_t thr_params;

> > >> +

> > >> +       args = calloc(1, sizeof(args_t));

> > >> +       if (args == NULL) {

> > >> +               LOG_ERR("Error: args mem alloc failed.\n");

> > >> +               exit(EXIT_FAILURE);

> > >> +       }

> > >> +

> > >> +       parse_args(argc, argv, &args->appl);

> > >> +

> > >> +       /* Init ODP before calling anything else */

> > >> +       if (odp_init_global(&instance, NULL, NULL)) {

> > >> +               LOG_ERR("Error: ODP global init failed.\n");

> > >> +               exit(EXIT_FAILURE);

> > >> +       }

> > >> +

> > >> +       /* Init this thread */

> > >> +       if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

> > >> +               LOG_ERR("Error: ODP local init failed.\n");

> > >> +               exit(EXIT_FAILURE);

> > >> +       }

> > >> +

> > >> +       num_workers = odp_cpumask_default_worker(&cpumask, 1);

> > >> +       (void)odp_cpumask_to_str(&cpumask, cpumaskstr,

> > >> sizeof(cpumaskstr));

> > >> +

> > >> +       /* Create packet pool */

> > >> +       odp_pool_param_init(&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_pool", &params);

> > >> +       if (pool == ODP_POOL_INVALID) {

> > >> +               LOG_ERR("Error: packet pool create failed.\n");

> > >> +               exit(EXIT_FAILURE);

> > >> +       }

> > >> +

> > >> +       args->appl.pktio = create_pktio(args->appl.file_name, pool);

> > >> +

> > >> +       /* Create and init worker threads */

> > >> +       memset(thread_tbl, 0, sizeof(thread_tbl));

> > >> +

> > >> +       memset(&thr_params, 0, sizeof(thr_params));

> > >> +       thr_params.thr_type = ODP_THREAD_WORKER;

> > >> +       thr_params.instance = instance;

> > >> +

> > >> +       cpu = odp_cpumask_first(&cpumask);

> > >> +       for (i = 0; i < num_workers; ++i) {

> > >> +               odp_cpumask_t thd_mask;

> > >> +               int (*thr_run_func)(void *);

> > >> +

> > >> +               thr_run_func = pktio_queue_thread;

> > >> +               /*

> > >> +                * Create threads one-by-one instead of all-at-once,

> > >> +                * because each thread might get different arguments.

> > >> +                * Calls odp_thread_create(cpu) for each thread

> > >> +                */

> > >> +               odp_cpumask_zero(&thd_mask);

> > >> +               odp_cpumask_set(&thd_mask, cpu);

> > >> +

> > >> +               thr_params.start = thr_run_func;

> > >> +               thr_params.arg   = &args;

> > >> +

> > >> +               odph_odpthreads_create(&thread_tbl[i], &thd_mask,

> > >> &thr_params);

> > >> +               cpu = odp_cpumask_next(&cpumask, cpu);

> > >> +       }

> > >> +

> > >> +       /* Master thread waits for other threads to exit */

> > >> +       for (i = 0; i < num_workers; ++i)

> > >> +               odph_odpthreads_join(&thread_tbl[i]);

> > >> +

> > >> +       odp_pktio_stop(args->appl.pktio);

> > >> +       odp_pktio_close(args->appl.pktio);

> > >> +

> > >> +       while (1) {

> > >> +               odp_event_t ev;

> > >> +

> > >> +               ev = odp_schedule(NULL, 0);

> > >> +               if (ev == ODP_EVENT_INVALID)

> > >> +                       break;

> > >> +       }

> > >> +

> > >> +       odp_pool_destroy(pool);

> > >> +       odp_term_local();

> > >> +       odp_term_global(instance);

> > >> +

> > >> +       if (packet_flags.all != args->appl.expected_bits.all) {

> > >> +               LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",

> > >> +                       packet_flags.all, args->appl.expected_bits.all);

> > >> +               free(args);

> > >> +               return -1;

> > >> +       }

> > >> +

> > >> +       free(args);

> > >> +       return 0;

> > >> +}

> > >> diff --git a/test/linux-generic/cls/cls_main.c

> > >> b/test/linux-generic/cls/cls_main.c

> > >> new file mode 100644

> > >> index 0000000..40179b9

> > >> --- /dev/null

> > >> +++ b/test/linux-generic/cls/cls_main.c

> > >> @@ -0,0 +1,12 @@

> > >> +/* Copyright (c) 2016, Linaro Limited

> > >> + * All rights reserved.

> > >> + *

> > >> + * SPDX-License-Identifier:     BSD-3-Clause

> > >> + */

> > >> +

> > >> +#include "cls_suites.h"

> > >> +

> > >> +int main(int argc, char *argv[])

> > >> +{

> > >> +       return cls_main(argc, argv);

> > >> +}

> > >> diff --git a/test/linux-generic/cls/cls_suites.h

> > >> b/test/linux-generic/cls/cls_suites.h

> > >> new file mode 100644

> > >> index 0000000..94c9b55

> > >> --- /dev/null

> > >> +++ b/test/linux-generic/cls/cls_suites.h

> > >> @@ -0,0 +1 @@

> > >> +int cls_main(int argc, char *argv[]);

> > >> diff --git a/test/linux-generic/cls/vlan.pcap

> > >> b/test/linux-generic/cls/vlan.pcap

> > >> new file mode 100644

> > >> index 0000000000000000000000000000000000000000..106ccb682e51495b40

> > >> 25337518a0bce63c2c7681

> > >> GIT binary patch

> > >> literal 9728

> > >> zcmeHNeQXrR6@R<F^Iq)3b|{=(C16{8IUt}71RM^-2~wIU*pOl>ikyh3QAN~9xK+}$

> > >> z4T)^-QnlAgC4W>Yk*X>mRlo92km}Nw!c|oiNTn)LBLcyK0BKSYLZiA0xI}f|@6FEc

> > >> z&CT8}Zu4i?dS2hYnK$pf`MuxF&iVB}9(>lN6zOYfipb#)S3BqRK6jeva#{)P%KZ4H

> > >> z2`Z!uf1f`})Rm#nP<lLnYk>-l2Nx8d?iyv8ohr8v56pV)=ly+yzZvNmzS?$(tvQ({

> > >> zN`3H(bKv=xSCLCcs6x0O=6jaXv{mjz%{=NyEc#gk|LwB0u=KHqz1)uIAM9Usn@mg_

> > >> zk2Z3jR&?;MUcTp8vTSb+>k8B@8d$;SEO~No<@;@ZpT?k%M|X%lk9|?s`aqYWyx8+Z

> > >> z0ekoid$_k!Cq3-<X$<;!oI~ik=uuzyOrT5ATGkaPBO2JlXV}BNmHltQH1XBQqGIxB

> > >> zljw+U^mWzt`dC-+XBzhK8TN2Tj(!$l@3W%oreFHHd@xpu)``6eKOy$gmCxBdp4?km

> > >> zcOk;wono&-@A$eG`7XZiNzwWmd-x3haEHC`0}y;QvZ#0!b{bfxaRTgY=FeI7XemDg

> > >> zrt~v(2bR#*#*@ZM8*9~NW2GVr#A;%NVz9F1ZjF^e?ya$>uoBL#iIo(6N4XHj>S(MG

> > >> zeb3ib&#l6WQUqAxJ_;+1G%sQ<6jmy<(AQPlQ&<V@nONzj-$&R}SgBCO*Ck?w=N1@3

> > >> ztzC_<r?BGDHD4ECg)ywKqF4*@npnxu3)8|1QTKm^m5M(TBzz!q>u6q?Ejk-3sTiy%

> > >> zJLqU*1*lbZW@5#)vBLROyi$q5N@&mI6<4qV_HQ01DswYP6#Khh&#x#j`~T|OCi|bb

> > >> zN3;J^@0;w82*T>sY!!z<-^(tatsc~D<=O~jv?n9bxA(ZuR@_G+(2YT0#YW(iMxbxc

> > >> zLZBOiz%;k6x2kCtQg)HA>t~@#46@u{#j=rA!7#$$CbB9q$Z}(l71}eARf%CCH-?2m

> > >> zdtf0!=0&0c`wW?qD??ss=9y8V-J`2{2h$^47+;s#M(N!gA6oF=4y70DLnrRc7wjFF

> > >> zOx)+JEMT8A&qVskA84dEJRcza81^~gx*CC0u1|&3bPQLjeGd2o2!%a`RQ9+oSCWm?

> > >> zfGfKtTAM4q7^HeU`u~Dd8B&mS{p)1}QkhfLdKua?kxJ7;D%*=(FFD6*y`<?OmF>l^

> > >> zmt?b5fB`qaKtG2kYe<9MTZQq~VxY+<h-x;~d#f3~&R#D=d**scG&arkGRI?>d#f#X

> > >> zC-1F%$Jh;<)qLNa>FllkkCp7lgq7o*eqgVOD_&tEZf{L=#F~HiI`-D;-3T*n&wsd=

> > >> zGr8jW-oxxwEwpEHg=cUD*#9!K|9#A<kf?o*vpIho*njMx$^K{hH2Xg}X0pFjF;}?S

> > >> zg?TY+W$2}>m0g;Fych=ZV%Eygp6u8k*ZU<ehJierftb<2IMr{9CIfj?pMlb(8K@Rj

> > >> z$o3L`#oxq<hN#m7mGe>mOo3LGZ$h?rzm4+*WW0SiRYs-<W}WF9Y1=#eX@6JA>+A&1

> > >> z6<~FR<Af&_1)NcsR@39<n_=~fdE4sQ?IRtJ?fAxsnnT~}v0Trei#VBp-~zsz<$QwZ

> > >> zhdl$C?4;5|r=G9K9Q(-%d8OMrIdwGG^Oqt{A0Ybbl^XN=lhQ-iCC@izetSZ-RQ+Es

> > >> zq7ope$T_TPtm>cZIbrB=T4CznDB`pN0v}Lu>#O=_=?(F(i=TJYjDJ}CKUqZOK;XlW

> > >> zW&ce>|FES$T?GCi@Bt?r&luyM7XKF29e=!tnt;HE4=wv=3_VUm%=ph1@rDb54>%Dq

> > >> z$3H9n?W;TfTSe3m1U~Gy?4LLEI6X1Pzfi<34+0->f|57lzaakAAOGzlY7PP){$$yI

> > >> z$I#=n#T@_LB6b82_<$3a7acH@#^1Z*-@Ll<|E&nzLEyuqyhAYUUo`YMoiX*7ia3dZ

> > >> z;A-ItTIyoYpzG&S@h;ZoU6)S)@O)!t$5R`F`pHhJ{%EiI)z;Ss3HYC|@IPqeU+H0A

> > >> z)kSUn{WAgI9~yd`*qHHOG4PL58xwz5#6O%M&W^0Vs|oo2m!ZcAk2(G|1OGVXF~`3q

> > >> z{ykZD{Ergw{cl5$6Crc_DFgo%)|>dB694LtPo--7+xT`x5BA^1?EeJsNFY&biu+J`

> > >> z4%q)ozcAT<=luh-6#JLUCj0BE!@HIlRYR$|s&F=CR#ig@)wZy1R#T<ws<Nx5(a_@@

> > >> z%N##bs;#PSqpC6`RMm2>s%&Icss8L9pLwC`YO5++s$O;MRi&*|y(-wKpH-@6Z5x#x

> > >> zrD|5SQFF5~>vsOT67sV!!T-ex{x3`L|JGRlfyPUW#!Z}ANYs9kR_0d$jlVvQ-3<__

> > >> zzBM_!y}xhg{UdE(-nw?Pv7elP)eUZ<)zxD4m~D0Fz)0JJ9Z^=tXR=k^G(w^(C$+LX

> > >> z7girQXI9S80aZDBhZpdHIlkcu_f4x3W^hfy3>Fe*@Q#ETyfa}2H^<Iku4ju>uwJ*p

> > >> zTm8nmq4bzs#b>qa#@2-RKWFH%k2WiOo53*HOPdU{P5i^@`pn36V=y7VpEvY)^Eb!e

> > >> zVKGe3V3-}kF!PyVnj;xT^+$eGzgmVFN|@hW3G@3v!u;+|nBRvI^1sK*|8Zmfl^*e_

> > >> z=jQy+d~7(#FE;^v<b46{KXnc71z)xDd&J1E(xbh4UYozK1^L4&Wi#|Q6Y}>&LjLw8

> > >> z<nLRt`2$xCe<G2qdWEZAvAJp&bJgDA`4a&H9tX3)>LcwAy~<gEMDpsP{Ow|OL!{M?

> > >> zy~CGxnpQXQw}sm|hc~d`YNjsQ!0+vN*2Ln_T-HGxxocg<Z{H-n@T)WE2V0J`$8Y@1

> > >> z4RoIL>tx#yoVIkz`Sa8B9XijSA(4^2mR}>0-BJ_Tss29B7e_YvoEaIu-^}r7-=$^F

> > >> z6~cGXX+DRoz`pSeQC2_O!0pfvZ7;gZocCA|HJ+)q%N#r>S}s!E9?#x$mpi>Ywi-))

> > >> zzlqPPulkI+{1I<Q$9P~!WW+Dz^Aho(8Sz_>=!jps-HaGs&hb6xvm83*LP+jfr{?Bf

> > >> zI_W|jxoaKf2D63d>gQgWH`vr!f<1NJC-ZiBu|or#2S`*D&f5H1L^1ZenkfFNqp0wI

> > >> zSNQ)QAvgyjv46|5;Cj<-r46np&s0uZI3frlYYB8{@6ZhP9)c)li1)B%M;7X4_~V3;

> > >> zweY?r!UwhjTaiBax{uQbVC0ia6YITCFtX0f?z#7McFRAtvy0s`aDWT^itOSU<``9e

> > >> z*o8Q9*E$t7pW+Ae-z3@9wtyG(Q9m~XI#usY+z*2OO@f;?E}jJRuan5`F(W(w6&+cA

> > >> zwHX;uyoe*XMIvi=PPq_Zq+RM4y2TP<&N=BqfRS9F>k(Zw`a|6ku?bs}H2&4@V19<y

> > >> zID}Ini24?e_AhE5T`)?NmT%$iQtg$F&ri|}c4@KSDc;0y{aiISvdwh*S?0(k1@)&>

> > >> zQ7plIU*=6|dR#J=D<oFhda1NSH5ognGq!{Y*RQl!v7!LwU*O1E{OJDRV*$_b-zLDq

> > >> zQO3ei&J^yz0(2S+l^`1m3)&VifIih&fKFqf!Wckb+_euHkKzNjM0<@#!v|j%=L2j_

> > >> H$A|v_$relS

> > >>

> > >> literal 0

> > >> HcmV?d00001

> > >>

> > >> diff --git a/test/linux-generic/cls/vlan_run.sh

> > >> b/test/linux-generic/cls/vlan_run.sh

> > >> new file mode 100755

> > >> index 0000000..7875eaf

> > >> --- /dev/null

> > >> +++ b/test/linux-generic/cls/vlan_run.sh

> > >> @@ -0,0 +1,49 @@

> > >> +#!/bin/sh

> > >> +#

> > >> +# Copyright (c) 2016, Linaro Limited

> > >> +# All rights reserved.

> > >> +#

> > >> +# SPDX-License-Identifier:      BSD-3-Clause

> > >> +#

> > >> +

> > >> +# directories where binary can be found:

> > >> +# -in the validation dir when running make check (intree or out of

> > tree)

> > >> +# -in the script directory, when running after 'make install', or

> > >> +# -in the validation when running standalone intree,

> > >> +# -in the _build directory, when running after 'make distcheck',

> > >> +# -in the current directory.

> > >> +# running stand alone out of tree requires setting PATH

> > >> +PATH=${TEST_DIR}/linux-generic/cls:$PATH

> > >> +PATH=$(dirname $0):$PATH

> > >> +PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH

> > >> +PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH

> > >> +PATH=.:$PATH

> > >> +

> > >> +bin_path=$(which cls_main${EXEEXT})

> > >> +if [ -x "$bin_path" ] ; then

> > >> +       echo "Running with $bin_path"

> > >> +else

> > >> +       echo "Cannot find cls_main${EXEEXT}"

> > >> +       echo "Please set you PATH for it. PATH=$PATH"

> > >> +fi

> > >> +

> > >> +# Test1: find vlan packets in pcap file and test internal

> > >> pkt_mmap_vlan_insert()

> > >> +#       function. Load packets from vlan.pcap file and check that

> > >> classifier

> > >> +#       set vlan bits fisible with odp_packet_has_vlan().

> > >> +

> > >> +PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`

> > >> +

> > >> +cls_main -i $PCAP -e 4097

> > >> +ret=$?

> > >> +

> > >> +PCAP_IN_SIZE=`stat -c %s $PCAP`

> > >> +PCAP_OUT_SIZE=`stat -c %s test_out.pcap`

> > >> +

> > >> +rm -f test_out.pcap

> > >> +

> > >> +if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; then

> > >> +       echo "Error: status ${ret}, in:${PCAP_IN_SIZE}

> > >> out:${PCAP_OUT_SIZE}"

> > >> +       exit 3

> > >> +fi

> > >> +

> > >> +echo "PASS: test 1 passed"

> > >> diff --git a/test/linux-generic/m4/configure.m4

> > >> b/test/linux-generic/m4/configure.m4

> > >> index 6b92201..1b722f6 100644

> > >> --- a/test/linux-generic/m4/configure.m4

> > >> +++ b/test/linux-generic/m4/configure.m4

> > >> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

> > >>   AC_CONFIG_FILES([test/linux-generic/Makefile

> > >>                  test/linux-generic/validation/api/shmem/Makefile

> > >>                  test/linux-generic/validation/api/pktio/Makefile

> > >> +                test/linux-generic/cls/Makefile

> > >>                  test/linux-generic/pktio_ipc/Makefile

> > >>                  test/linux-generic/ring/Makefile

> > >>                  test/linux-generic/performance/Makefile])

> > >>

> > >

> > >

> >

> >

> > --

> > Mike Holmes

> > Program Manager - Linaro Networking Group

> > Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs

> > "Work should be fun and collaborative, the rest follows"

> >


-- 
Anders Roxell
anders.roxell@linaro.org
M: +46 709 71 42 85 | IRC: roxell
Maxim Uvarov Sept. 15, 2016, 8:24 a.m. | #7
On 09/14/16 21:45, Anders Roxell wrote:
> On 2016-09-12 19:54, Bill Fischofer wrote:

>> On Mon, Sep 12, 2016 at 10:24 AM, Mike Holmes <mike.holmes@linaro.org>

>> wrote:

>>

>>> On 12 September 2016 at 10:43, Maxim Uvarov <maxim.uvarov@linaro.org>

>>> wrote:

>>>

>>>> if no comments than it can be merged?

>>>

>>> Not without a review, I am interested in this capability but I have not

>>> reviewed it.

>>>

>> I had previously reviewed and tested v2 of this patch. v3 just incorporates

>> some additional comments by Anders. If Anders has no objection, my review

>> can be propagated to v3.

> I don't think we resolved this issue raised [1], and you (Bill) had a

> comment about not screwing up performance while tinkering with it [2].

>

> Cheers,

> Anders

> [1] https://lists.linaro.org/pipermail/lng-odp/2016-August/025421.html

> [2] https://lists.linaro.org/pipermail/lng-odp/2016-August/025407.html


Old patch I already forgot all discussion about it.  From mailing list I 
see that
you were ok to include it to linux-gen first:

https://lists.linaro.org/pipermail/lng-odp/2016-August/025421.html

So if I'm right 2 things needed to be done:
1) rework bit fields
2) fix Makefile.am to run sequence for make check in right order.

Am I correct?

Maxim.

>>

>>> I really believe ODP shoudl have as part of the validation the ability to

>>> pass packet streams though and confirm the exact result on the far side,

>>> Krishna ran into this issue with crypto on odp-dpdk which was giving

>>> different results.

>>>

>>>

>>>>

>>>> Maxim.

>>>>

>>>> On 08/29/16 10:50, Maxim Uvarov wrote:

>>>>

>>>>> add pcap play back test which takes 2 arguments: 1 - pcap file,

>>>>> 2 - packet mask to match. Intend is to test odp with different

>>>>> input traffic to check internal implementation functions. In

>>>>> current case it's test for vlan tag instertion for packet mmap:

>>>>> pkt_mmap_vlan_insert().

>>>>>

>>>>> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

>>>>> ---

>>>>>    v3: fix comments noted by Anders

>>>>>

>>>>>    test/linux-generic/.gitignore       |   1 +

>>>>>    test/linux-generic/Makefile.am      |  10 +-

>>>>>    test/linux-generic/cls/.gitignore   |   1 +

>>>>>    test/linux-generic/cls/Makefile.am  |  13 ++

>>>>>    test/linux-generic/cls/cls.c        | 351

>>> ++++++++++++++++++++++++++++++

>>>>> ++++++

>>>>>    test/linux-generic/cls/cls_main.c   |  12 ++

>>>>>    test/linux-generic/cls/cls_suites.h |   1 +

>>>>>    test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes

>>>>>    test/linux-generic/cls/vlan_run.sh  |  49 +++++

>>>>>    test/linux-generic/m4/configure.m4  |   1 +

>>>>>    10 files changed, 435 insertions(+), 4 deletions(-)

>>>>>    create mode 100644 test/linux-generic/cls/.gitignore

>>>>>    create mode 100644 test/linux-generic/cls/Makefile.am

>>>>>    create mode 100644 test/linux-generic/cls/cls.c

>>>>>    create mode 100644 test/linux-generic/cls/cls_main.c

>>>>>    create mode 100644 test/linux-generic/cls/cls_suites.h

>>>>>    create mode 100644 test/linux-generic/cls/vlan.pcap

>>>>>    create mode 100755 test/linux-generic/cls/vlan_run.sh

>>>>>

>>>>> diff --git a/test/linux-generic/.gitignore

>>> b/test/linux-generic/.gitignor

>>>>> e

>>>>> index 5dabf91..f65c7c1 100644

>>>>> --- a/test/linux-generic/.gitignore

>>>>> +++ b/test/linux-generic/.gitignore

>>>>> @@ -1,3 +1,4 @@

>>>>>    *.log

>>>>>    *.trs

>>>>>    tests-validation.env

>>>>> +test_out.pcap

>>>>> diff --git a/test/linux-generic/Makefile.am

>>>>> b/test/linux-generic/Makefile.am

>>>>> index 4660cf0..2554f8e 100644

>>>>> --- a/test/linux-generic/Makefile.am

>>>>> +++ b/test/linux-generic/Makefile.am

>>>>> @@ -1,5 +1,8 @@

>>>>>    include $(top_srcdir)/test/Makefile.inc

>>>>>    TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/

>>>>> common_plat/validation

>>>>> +TEST_EXTENSIONS = .sh

>>>>> +

>>>>> +dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>>>>>      ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_pl

>>>>> at/validation/api

>>>>>    @@ -37,11 +40,14 @@ TESTS = validation/api/pktio/pktio_run.sh \

>>>>>      SUBDIRS += validation/api/pktio\

>>>>>             validation/api/shmem\

>>>>> +          cls\

>>>>>             pktio_ipc\

>>>>>             ring

>>>>>      if HAVE_PCAP

>>>>>    TESTS += validation/api/pktio/pktio_run_pcap.sh

>>>>> +TESTS += cls/vlan_run.sh

>>>>> +dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap

>>>>>    endif

>>>>>    if netmap_support

>>>>>    TESTS += validation/api/pktio/pktio_run_netmap.sh

>>>>> @@ -61,10 +67,6 @@ SUBDIRS += validation/api/pktio

>>>>>    endif

>>>>>    endif

>>>>>    -TEST_EXTENSIONS = .sh

>>>>> -

>>>>> -dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>>>>> -

>>>>>    test_SCRIPTS = $(dist_check_SCRIPTS)

>>>>>      tests-validation.env:

>>>>> diff --git a/test/linux-generic/cls/.gitignore

>>>>> b/test/linux-generic/cls/.gitignore

>>>>> new file mode 100644

>>>>> index 0000000..5a652b7

>>>>> --- /dev/null

>>>>> +++ b/test/linux-generic/cls/.gitignore

>>>>> @@ -0,0 +1 @@

>>>>> +cls_main

>>>>> diff --git a/test/linux-generic/cls/Makefile.am

>>>>> b/test/linux-generic/cls/Makefile.am

>>>>> new file mode 100644

>>>>> index 0000000..43fb0bc

>>>>> --- /dev/null

>>>>> +++ b/test/linux-generic/cls/Makefile.am

>>>>> @@ -0,0 +1,13 @@

>>>>> +include ../Makefile.inc

>>>>> +

>>>>> +noinst_LTLIBRARIES = libtestcls.la

>>>>> +libtestcls_la_SOURCES = cls.c

>>>>> +libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)

>>>>> +

>>>>> +test_PROGRAMS = cls_main$(EXEEXT)

>>>>> +dist_cls_main_SOURCES = cls_main.c

>>>>> +

>>>>> +cls_main_LDFLAGS = $(AM_LDFLAGS)

>>>>> +cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)

>>>>> +

>>>>> +noinst_HEADERS = cls_suites.h

>>>>> diff --git a/test/linux-generic/cls/cls.c b/test/linux-generic/cls/cls.c

>>>>> new file mode 100644

>>>>> index 0000000..f6df30a

>>>>> --- /dev/null

>>>>> +++ b/test/linux-generic/cls/cls.c

>>>>> @@ -0,0 +1,351 @@

>>>>> +/* Copyright (c) 2016, Linaro Limited

>>>>> + * All rights reserved.

>>>>> + *

>>>>> + * SPDX-License-Identifier:     BSD-3-Clause

>>>>> + */

>>>>> +

>>>>> +#include <stdlib.h>

>>>>> +#include <string.h>

>>>>> +#include <getopt.h>

>>>>> +#include <unistd.h>

>>>>> +#include <inttypes.h>

>>>>> +

>>>>> +#include <test_debug.h>

>>>>> +

>>>>> +#include <odp_api.h>

>>>>> +#include <odp/helper/linux.h>

>>>>> +#include <odp/helper/eth.h>

>>>>> +#include <odp/helper/ip.h>

>>>>> +

>>>>> +#include <odp_packet_internal.h>

>>>>> +

>>>>> +#include "cls_suites.h"

>>>>> +

>>>>> +/** Get rid of path in filename - only for unix-type paths using '/' */

>>>>> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \

>>>>> +                           strrchr((file_name), '/') + 1 : (file_name))

>>>>> +

>>>>> +/**

>>>>> + * Print usage information

>>>>> + */

>>>>> +static void usage(char *progname)

>>>>> +{

>>>>> +       printf("\n"

>>>>> +              "This is test application to verify that linux-generic

>>>>> classifier\n"

>>>>> +              "correctly classifies packets on input. Main intend is

>>> add

>>>>> more code\n"

>>>>> +              "coverage for internal functions playing different

>>> traffic

>>>>> recorded to\n"

>>>>> +              "pcap files."

>>>>> +              "\n"

>>>>> +              "Usage: %s OPTIONS\n"

>>>>> +              "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"

>>>>> +              "\n"

>>>>> +              "Mandatory OPTIONS:\n"

>>>>> +              "  -i, pcap file name\n"

>>>>> +              "  -e, expected packet bitmask\n"

>>>>> +              "\n", NO_PATH(progname), NO_PATH(progname)

>>>>> +           );

>>>>> +}

>>>>> +

>>>>> +/** @def SHM_PKT_POOL_SIZE

>>>>> + * @brief Size of the shared memory block

>>>>> + */

>>>>> +#define SHM_PKT_POOL_SIZE      512

>>>>> +

>>>>> +/** @def SHM_PKT_POOL_BUF_SIZE

>>>>> + * @brief Buffer size of the packet pool buffer

>>>>> + */

>>>>> +#define SHM_PKT_POOL_BUF_SIZE  1856

>>>>> +

>>>>> +/**

>>>>> + * Parsed command line application arguments

>>>>> + */

>>>>> +typedef struct {

>>>>> +       char *file_name;     /**< File name for pcap pktio */

>>>>> +       odp_pktio_t pktio;  /**< Pktio dev */

>>>>> +       input_flags_t expected_bits; /**< Expected bits from test run */

>>>>> +} appl_args_t;

>>>>> +

>>>>> +/**

>>>>> + * Grouping of both parsed CL args and thread specific args - alloc

>>>>> together

>>>>> + */

>>>>> +typedef struct {

>>>>> +       /** Application (parsed) arguments */

>>>>> +       appl_args_t appl;

>>>>> +} args_t;

>>>>> +

>>>>> +/** Global pointer to args */

>>>>> +static args_t *args;

>>>>> +/** Fill this bit struct to check which packet fields were classified

>>> */

>>>>> +static input_flags_t packet_flags;

>>>>> +

>>>>> +/**

>>>>> + * Parse and store the command line arguments

>>>>> + *

>>>>> + * @param argc       argument count

>>>>> + * @param argv[]     argument vector

>>>>> + * @param appl_args  Store application arguments here

>>>>> + */

>>>>> +static void parse_args(int argc, char *argv[], appl_args_t *appl_args)

>>>>> +{

>>>>> +       int opt;

>>>>> +       int long_index;

>>>>> +       static const struct option longopts[] = {

>>>>> +               {"interface", required_argument, NULL, 'i'},    /*

>>> return

>>>>> 'i' */

>>>>> +               {"extected", required_argument, NULL, 'e'},     /*

>>> return

>>>>> 'e' */

>>>>> +               {"help", no_argument, NULL, 'h'},               /*

>>> return

>>>>> 'h' */

>>>>> +               {NULL, 0, NULL, 0}

>>>>> +       };

>>>>> +

>>>>> +       static const char *shortopts = ":i:e:h";

>>>>> +

>>>>> +       /* let helper collect its own arguments (e.g. --odph_proc) */

>>>>> +       odph_parse_options(argc, argv, shortopts, longopts);

>>>>> +

>>>>> +       appl_args->file_name = NULL;

>>>>> +       opterr = 0; /* do not issue errors on helper options */

>>>>> +       appl_args->expected_bits.all = 0;

>>>>> +

>>>>> +       while (1) {

>>>>> +               opt = getopt_long(argc, argv, shortopts, longopts,

>>>>> &long_index);

>>>>> +

>>>>> +               if (opt == -1)

>>>>> +                       break;  /* No more options */

>>>>> +

>>>>> +               switch (opt) {

>>>>> +               case 'i':

>>>>> +                       appl_args->file_name =  optarg;

>>>>> +                       break;

>>>>> +               case 'e':

>>>>> +                       appl_args->expected_bits.all = atoll(optarg);

>>>>> +                       break;

>>>>> +

>>>>> +               case 'h':

>>>>> +                       usage(argv[0]);

>>>>> +                       exit(EXIT_SUCCESS);

>>>>> +                       break;

>>>>> +               default:

>>>>> +                       break;

>>>>> +               }

>>>>> +       }

>>>>> +

>>>>> +       if (!appl_args->file_name) {

>>>>> +               usage(argv[0]);

>>>>> +               exit(EXIT_SUCCESS);

>>>>> +       }

>>>>> +

>>>>> +       optind = 1;             /* reset 'extern optind' from the getopt

>>>>> lib */

>>>>> +}

>>>>> +

>>>>> +/**

>>>>> + * Create a pktio handle and configure in/out queues.

>>>>> + *

>>>>> + * @param fname Name of device to open

>>>>> + * @param pool Pool to associate with device for packet RX/TX

>>>>> + *

>>>>> + * @return The handle of the created pktio object.

>>>>> + * @retval ODP_PKTIO_INVALID if the create fails.

>>>>> + */

>>>>> +static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)

>>>>> +{

>>>>> +       odp_pktio_t pktio;

>>>>> +       int ret;

>>>>> +       odp_pktio_param_t pktio_param;

>>>>> +       odp_pktin_queue_param_t pktin_param;

>>>>> +       char dev[255];

>>>>> +

>>>>> +       odp_pktio_param_init(&pktio_param);

>>>>> +       pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;

>>>>> +

>>>>> +       memset(dev, 0, 255);

>>>>> +       sprintf(dev, "pcap:in=%s:out=test_out.pcap",  fname);

>>>>> +

>>>>> +       /* Open a packet IO instance */

>>>>> +       pktio = odp_pktio_open(dev, pool, &pktio_param);

>>>>> +       if (pktio == ODP_PKTIO_INVALID)

>>>>> +               LOG_ABORT("Error: pktio create failed for %s\n", dev);

>>>>> +

>>>>> +       odp_pktin_queue_param_init(&pktin_param);

>>>>> +

>>>>> +       pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;

>>>>> +

>>>>> +       if (odp_pktin_queue_config(pktio, &pktin_param))

>>>>> +               LOG_ABORT("Error: pktin config failed for %s\n", dev);

>>>>> +

>>>>> +       if (odp_pktout_queue_config(pktio, NULL))

>>>>> +               LOG_ABORT("Error: pktout config failed for %s\n", dev);

>>>>> +

>>>>> +       ret = odp_pktio_start(pktio);

>>>>> +       if (ret != 0)

>>>>> +               LOG_ABORT("Error: unable to start %s\n", dev);

>>>>> +

>>>>> +       printf("  created pktio:%02" PRIu64

>>>>> +              ", dev:%s, queue mode (ATOMIC queues)\n"

>>>>> +              "  \tdefault pktio%02" PRIu64 "\n",

>>>>> +              odp_pktio_to_u64(pktio), dev,

>>>>> +              odp_pktio_to_u64(pktio));

>>>>> +

>>>>> +       return pktio;

>>>>> +}

>>>>> +

>>>>> +/**

>>>>> + * Packet IO loopback worker thread using ODP queues

>>>>> + *

>>>>> + * @param arg  thread arguments of type 'thread_args_t *'

>>>>> + *

>>>>> + * @return 0 on success

>>>>> + * @return !0 on any error

>>>>> + */

>>>>> +static int pktio_queue_thread(void *arg ODP_UNUSED)

>>>>> +{

>>>>> +       int thr = odp_thread_id();

>>>>> +       odp_pktout_queue_t pktout;

>>>>> +       odp_packet_t pkt;

>>>>> +       odp_event_t ev;

>>>>> +       uint64_t sched_wait = odp_schedule_wait_time(ODP_

>>> TIME_MSEC_IN_NS

>>>>> * 100);

>>>>> +

>>>>> +       packet_flags.all = 0;

>>>>> +

>>>>> +       /* Loop packets */

>>>>> +       while (1) {

>>>>> +               odp_pktio_t pktio_tmp;

>>>>> +

>>>>> +               ev = odp_schedule(NULL, sched_wait);

>>>>> +               if (ev == ODP_EVENT_INVALID)

>>>>> +                       break;

>>>>> +

>>>>> +               pkt = odp_packet_from_event(ev);

>>>>> +               if (!odp_packet_is_valid(pkt))

>>>>> +                       continue;

>>>>> +

>>>>> +               pktio_tmp = odp_packet_input(pkt);

>>>>> +

>>>>> +               if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {

>>>>> +                       LOG_ERR("  [%02i] Error: no pktout queue\n",

>>> thr);

>>>>> +                       return -1;

>>>>> +               }

>>>>> +

>>>>> +               /* Extend bits here for more additional tests */

>>>>> +               if (odp_packet_has_l2(pkt))

>>>>> +                       packet_flags.parsed_l2 = 1;

>>>>> +               if (odp_packet_has_vlan(pkt))

>>>>> +                       packet_flags.vlan = 1;

>>>>> +

>>>>> +               /* Enqueue the packet for output */

>>>>> +               if (odp_pktout_send(pktout, &pkt, 1) != 1) {

>>>>> +                       LOG_ERR("  [%i] Packet send failed.\n", thr);

>>>>> +                       odp_packet_free(pkt);

>>>>> +                       continue;

>>>>> +               }

>>>>> +       }

>>>>> +

>>>>> +       return 0;

>>>>> +}

>>>>> +

>>>>> +int cls_main(int argc, char *argv[])

>>>>> +{

>>>>> +       odph_odpthread_t thread_tbl[1];

>>>>> +       odp_pool_t pool;

>>>>> +       int num_workers;

>>>>> +       int i;

>>>>> +       int cpu;

>>>>> +       odp_cpumask_t cpumask;

>>>>> +       char cpumaskstr[ODP_CPUMASK_STR_SIZE];

>>>>> +       odp_pool_param_t params;

>>>>> +       odp_instance_t instance;

>>>>> +       odph_odpthread_params_t thr_params;

>>>>> +

>>>>> +       args = calloc(1, sizeof(args_t));

>>>>> +       if (args == NULL) {

>>>>> +               LOG_ERR("Error: args mem alloc failed.\n");

>>>>> +               exit(EXIT_FAILURE);

>>>>> +       }

>>>>> +

>>>>> +       parse_args(argc, argv, &args->appl);

>>>>> +

>>>>> +       /* Init ODP before calling anything else */

>>>>> +       if (odp_init_global(&instance, NULL, NULL)) {

>>>>> +               LOG_ERR("Error: ODP global init failed.\n");

>>>>> +               exit(EXIT_FAILURE);

>>>>> +       }

>>>>> +

>>>>> +       /* Init this thread */

>>>>> +       if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

>>>>> +               LOG_ERR("Error: ODP local init failed.\n");

>>>>> +               exit(EXIT_FAILURE);

>>>>> +       }

>>>>> +

>>>>> +       num_workers = odp_cpumask_default_worker(&cpumask, 1);

>>>>> +       (void)odp_cpumask_to_str(&cpumask, cpumaskstr,

>>>>> sizeof(cpumaskstr));

>>>>> +

>>>>> +       /* Create packet pool */

>>>>> +       odp_pool_param_init(&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_pool", &params);

>>>>> +       if (pool == ODP_POOL_INVALID) {

>>>>> +               LOG_ERR("Error: packet pool create failed.\n");

>>>>> +               exit(EXIT_FAILURE);

>>>>> +       }

>>>>> +

>>>>> +       args->appl.pktio = create_pktio(args->appl.file_name, pool);

>>>>> +

>>>>> +       /* Create and init worker threads */

>>>>> +       memset(thread_tbl, 0, sizeof(thread_tbl));

>>>>> +

>>>>> +       memset(&thr_params, 0, sizeof(thr_params));

>>>>> +       thr_params.thr_type = ODP_THREAD_WORKER;

>>>>> +       thr_params.instance = instance;

>>>>> +

>>>>> +       cpu = odp_cpumask_first(&cpumask);

>>>>> +       for (i = 0; i < num_workers; ++i) {

>>>>> +               odp_cpumask_t thd_mask;

>>>>> +               int (*thr_run_func)(void *);

>>>>> +

>>>>> +               thr_run_func = pktio_queue_thread;

>>>>> +               /*

>>>>> +                * Create threads one-by-one instead of all-at-once,

>>>>> +                * because each thread might get different arguments.

>>>>> +                * Calls odp_thread_create(cpu) for each thread

>>>>> +                */

>>>>> +               odp_cpumask_zero(&thd_mask);

>>>>> +               odp_cpumask_set(&thd_mask, cpu);

>>>>> +

>>>>> +               thr_params.start = thr_run_func;

>>>>> +               thr_params.arg   = &args;

>>>>> +

>>>>> +               odph_odpthreads_create(&thread_tbl[i], &thd_mask,

>>>>> &thr_params);

>>>>> +               cpu = odp_cpumask_next(&cpumask, cpu);

>>>>> +       }

>>>>> +

>>>>> +       /* Master thread waits for other threads to exit */

>>>>> +       for (i = 0; i < num_workers; ++i)

>>>>> +               odph_odpthreads_join(&thread_tbl[i]);

>>>>> +

>>>>> +       odp_pktio_stop(args->appl.pktio);

>>>>> +       odp_pktio_close(args->appl.pktio);

>>>>> +

>>>>> +       while (1) {

>>>>> +               odp_event_t ev;

>>>>> +

>>>>> +               ev = odp_schedule(NULL, 0);

>>>>> +               if (ev == ODP_EVENT_INVALID)

>>>>> +                       break;

>>>>> +       }

>>>>> +

>>>>> +       odp_pool_destroy(pool);

>>>>> +       odp_term_local();

>>>>> +       odp_term_global(instance);

>>>>> +

>>>>> +       if (packet_flags.all != args->appl.expected_bits.all) {

>>>>> +               LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",

>>>>> +                       packet_flags.all, args->appl.expected_bits.all);

>>>>> +               free(args);

>>>>> +               return -1;

>>>>> +       }

>>>>> +

>>>>> +       free(args);

>>>>> +       return 0;

>>>>> +}

>>>>> diff --git a/test/linux-generic/cls/cls_main.c

>>>>> b/test/linux-generic/cls/cls_main.c

>>>>> new file mode 100644

>>>>> index 0000000..40179b9

>>>>> --- /dev/null

>>>>> +++ b/test/linux-generic/cls/cls_main.c

>>>>> @@ -0,0 +1,12 @@

>>>>> +/* Copyright (c) 2016, Linaro Limited

>>>>> + * All rights reserved.

>>>>> + *

>>>>> + * SPDX-License-Identifier:     BSD-3-Clause

>>>>> + */

>>>>> +

>>>>> +#include "cls_suites.h"

>>>>> +

>>>>> +int main(int argc, char *argv[])

>>>>> +{

>>>>> +       return cls_main(argc, argv);

>>>>> +}

>>>>> diff --git a/test/linux-generic/cls/cls_suites.h

>>>>> b/test/linux-generic/cls/cls_suites.h

>>>>> new file mode 100644

>>>>> index 0000000..94c9b55

>>>>> --- /dev/null

>>>>> +++ b/test/linux-generic/cls/cls_suites.h

>>>>> @@ -0,0 +1 @@

>>>>> +int cls_main(int argc, char *argv[]);

>>>>> diff --git a/test/linux-generic/cls/vlan.pcap

>>>>> b/test/linux-generic/cls/vlan.pcap

>>>>> new file mode 100644

>>>>> index 0000000000000000000000000000000000000000..106ccb682e51495b40

>>>>> 25337518a0bce63c2c7681

>>>>> GIT binary patch

>>>>> literal 9728

>>>>> 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

>>>>> H$A|v_$relS

>>>>>

>>>>> literal 0

>>>>> HcmV?d00001

>>>>>

>>>>> diff --git a/test/linux-generic/cls/vlan_run.sh

>>>>> b/test/linux-generic/cls/vlan_run.sh

>>>>> new file mode 100755

>>>>> index 0000000..7875eaf

>>>>> --- /dev/null

>>>>> +++ b/test/linux-generic/cls/vlan_run.sh

>>>>> @@ -0,0 +1,49 @@

>>>>> +#!/bin/sh

>>>>> +#

>>>>> +# Copyright (c) 2016, Linaro Limited

>>>>> +# All rights reserved.

>>>>> +#

>>>>> +# SPDX-License-Identifier:      BSD-3-Clause

>>>>> +#

>>>>> +

>>>>> +# directories where binary can be found:

>>>>> +# -in the validation dir when running make check (intree or out of

>>> tree)

>>>>> +# -in the script directory, when running after 'make install', or

>>>>> +# -in the validation when running standalone intree,

>>>>> +# -in the _build directory, when running after 'make distcheck',

>>>>> +# -in the current directory.

>>>>> +# running stand alone out of tree requires setting PATH

>>>>> +PATH=${TEST_DIR}/linux-generic/cls:$PATH

>>>>> +PATH=$(dirname $0):$PATH

>>>>> +PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH

>>>>> +PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH

>>>>> +PATH=.:$PATH

>>>>> +

>>>>> +bin_path=$(which cls_main${EXEEXT})

>>>>> +if [ -x "$bin_path" ] ; then

>>>>> +       echo "Running with $bin_path"

>>>>> +else

>>>>> +       echo "Cannot find cls_main${EXEEXT}"

>>>>> +       echo "Please set you PATH for it. PATH=$PATH"

>>>>> +fi

>>>>> +

>>>>> +# Test1: find vlan packets in pcap file and test internal

>>>>> pkt_mmap_vlan_insert()

>>>>> +#       function. Load packets from vlan.pcap file and check that

>>>>> classifier

>>>>> +#       set vlan bits fisible with odp_packet_has_vlan().

>>>>> +

>>>>> +PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`

>>>>> +

>>>>> +cls_main -i $PCAP -e 4097

>>>>> +ret=$?

>>>>> +

>>>>> +PCAP_IN_SIZE=`stat -c %s $PCAP`

>>>>> +PCAP_OUT_SIZE=`stat -c %s test_out.pcap`

>>>>> +

>>>>> +rm -f test_out.pcap

>>>>> +

>>>>> +if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; then

>>>>> +       echo "Error: status ${ret}, in:${PCAP_IN_SIZE}

>>>>> out:${PCAP_OUT_SIZE}"

>>>>> +       exit 3

>>>>> +fi

>>>>> +

>>>>> +echo "PASS: test 1 passed"

>>>>> diff --git a/test/linux-generic/m4/configure.m4

>>>>> b/test/linux-generic/m4/configure.m4

>>>>> index 6b92201..1b722f6 100644

>>>>> --- a/test/linux-generic/m4/configure.m4

>>>>> +++ b/test/linux-generic/m4/configure.m4

>>>>> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

>>>>>    AC_CONFIG_FILES([test/linux-generic/Makefile

>>>>>                   test/linux-generic/validation/api/shmem/Makefile

>>>>>                   test/linux-generic/validation/api/pktio/Makefile

>>>>> +                test/linux-generic/cls/Makefile

>>>>>                   test/linux-generic/pktio_ipc/Makefile

>>>>>                   test/linux-generic/ring/Makefile

>>>>>                   test/linux-generic/performance/Makefile])

>>>>>

>>>>

>>>

>>> --

>>> Mike Holmes

>>> Program Manager - Linaro Networking Group

>>> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs

>>> "Work should be fun and collaborative, the rest follows"

>>>
Maxim Uvarov Sept. 15, 2016, 8:41 a.m. | #8
On 09/15/16 11:24, Maxim Uvarov wrote:
> On 09/14/16 21:45, Anders Roxell wrote:

>> On 2016-09-12 19:54, Bill Fischofer wrote:

>>> On Mon, Sep 12, 2016 at 10:24 AM, Mike Holmes <mike.holmes@linaro.org>

>>> wrote:

>>>

>>>> On 12 September 2016 at 10:43, Maxim Uvarov <maxim.uvarov@linaro.org>

>>>> wrote:

>>>>

>>>>> if no comments than it can be merged?

>>>>

>>>> Not without a review, I am interested in this capability but I have 

>>>> not

>>>> reviewed it.

>>>>

>>> I had previously reviewed and tested v2 of this patch. v3 just 

>>> incorporates

>>> some additional comments by Anders. If Anders has no objection, my 

>>> review

>>> can be propagated to v3.

>> I don't think we resolved this issue raised [1], and you (Bill) had a

>> comment about not screwing up performance while tinkering with it [2].

>>

>> Cheers,

>> Anders

>> [1] https://lists.linaro.org/pipermail/lng-odp/2016-August/025421.html

>> [2] https://lists.linaro.org/pipermail/lng-odp/2016-August/025407.html

>

> Old patch I already forgot all discussion about it.  From mailing list 

> I see that

> you were ok to include it to linux-gen first:

>

> https://lists.linaro.org/pipermail/lng-odp/2016-August/025421.html

>

> So if I'm right 2 things needed to be done:

> 1) rework bit fields

> 2) fix Makefile.am to run sequence for make check in right order.

>

> Am I correct?

>

> Maxim.


I'm sorry, 2 is not related to this patch.  I will try to send v4 for 
current patch with bit field fixes.

Maxim.

>

>>>

>>>> I really believe ODP shoudl have as part of the validation the 

>>>> ability to

>>>> pass packet streams though and confirm the exact result on the far 

>>>> side,

>>>> Krishna ran into this issue with crypto on odp-dpdk which was giving

>>>> different results.

>>>>

>>>>

>>>>>

>>>>> Maxim.

>>>>>

>>>>> On 08/29/16 10:50, Maxim Uvarov wrote:

>>>>>

>>>>>> add pcap play back test which takes 2 arguments: 1 - pcap file,

>>>>>> 2 - packet mask to match. Intend is to test odp with different

>>>>>> input traffic to check internal implementation functions. In

>>>>>> current case it's test for vlan tag instertion for packet mmap:

>>>>>> pkt_mmap_vlan_insert().

>>>>>>

>>>>>> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

>>>>>> ---

>>>>>>    v3: fix comments noted by Anders

>>>>>>

>>>>>>    test/linux-generic/.gitignore       |   1 +

>>>>>>    test/linux-generic/Makefile.am      |  10 +-

>>>>>>    test/linux-generic/cls/.gitignore   |   1 +

>>>>>>    test/linux-generic/cls/Makefile.am  |  13 ++

>>>>>>    test/linux-generic/cls/cls.c        | 351

>>>> ++++++++++++++++++++++++++++++

>>>>>> ++++++

>>>>>>    test/linux-generic/cls/cls_main.c   |  12 ++

>>>>>>    test/linux-generic/cls/cls_suites.h |   1 +

>>>>>>    test/linux-generic/cls/vlan.pcap    | Bin 0 -> 9728 bytes

>>>>>>    test/linux-generic/cls/vlan_run.sh  |  49 +++++

>>>>>>    test/linux-generic/m4/configure.m4  |   1 +

>>>>>>    10 files changed, 435 insertions(+), 4 deletions(-)

>>>>>>    create mode 100644 test/linux-generic/cls/.gitignore

>>>>>>    create mode 100644 test/linux-generic/cls/Makefile.am

>>>>>>    create mode 100644 test/linux-generic/cls/cls.c

>>>>>>    create mode 100644 test/linux-generic/cls/cls_main.c

>>>>>>    create mode 100644 test/linux-generic/cls/cls_suites.h

>>>>>>    create mode 100644 test/linux-generic/cls/vlan.pcap

>>>>>>    create mode 100755 test/linux-generic/cls/vlan_run.sh

>>>>>>

>>>>>> diff --git a/test/linux-generic/.gitignore

>>>> b/test/linux-generic/.gitignor

>>>>>> e

>>>>>> index 5dabf91..f65c7c1 100644

>>>>>> --- a/test/linux-generic/.gitignore

>>>>>> +++ b/test/linux-generic/.gitignore

>>>>>> @@ -1,3 +1,4 @@

>>>>>>    *.log

>>>>>>    *.trs

>>>>>>    tests-validation.env

>>>>>> +test_out.pcap

>>>>>> diff --git a/test/linux-generic/Makefile.am

>>>>>> b/test/linux-generic/Makefile.am

>>>>>> index 4660cf0..2554f8e 100644

>>>>>> --- a/test/linux-generic/Makefile.am

>>>>>> +++ b/test/linux-generic/Makefile.am

>>>>>> @@ -1,5 +1,8 @@

>>>>>>    include $(top_srcdir)/test/Makefile.inc

>>>>>>    TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/

>>>>>> common_plat/validation

>>>>>> +TEST_EXTENSIONS = .sh

>>>>>> +

>>>>>> +dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>>>>>>      ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_pl

>>>>>> at/validation/api

>>>>>>    @@ -37,11 +40,14 @@ TESTS = validation/api/pktio/pktio_run.sh \

>>>>>>      SUBDIRS += validation/api/pktio\

>>>>>>             validation/api/shmem\

>>>>>> +          cls\

>>>>>>             pktio_ipc\

>>>>>>             ring

>>>>>>      if HAVE_PCAP

>>>>>>    TESTS += validation/api/pktio/pktio_run_pcap.sh

>>>>>> +TESTS += cls/vlan_run.sh

>>>>>> +dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap

>>>>>>    endif

>>>>>>    if netmap_support

>>>>>>    TESTS += validation/api/pktio/pktio_run_netmap.sh

>>>>>> @@ -61,10 +67,6 @@ SUBDIRS += validation/api/pktio

>>>>>>    endif

>>>>>>    endif

>>>>>>    -TEST_EXTENSIONS = .sh

>>>>>> -

>>>>>> -dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)

>>>>>> -

>>>>>>    test_SCRIPTS = $(dist_check_SCRIPTS)

>>>>>>      tests-validation.env:

>>>>>> diff --git a/test/linux-generic/cls/.gitignore

>>>>>> b/test/linux-generic/cls/.gitignore

>>>>>> new file mode 100644

>>>>>> index 0000000..5a652b7

>>>>>> --- /dev/null

>>>>>> +++ b/test/linux-generic/cls/.gitignore

>>>>>> @@ -0,0 +1 @@

>>>>>> +cls_main

>>>>>> diff --git a/test/linux-generic/cls/Makefile.am

>>>>>> b/test/linux-generic/cls/Makefile.am

>>>>>> new file mode 100644

>>>>>> index 0000000..43fb0bc

>>>>>> --- /dev/null

>>>>>> +++ b/test/linux-generic/cls/Makefile.am

>>>>>> @@ -0,0 +1,13 @@

>>>>>> +include ../Makefile.inc

>>>>>> +

>>>>>> +noinst_LTLIBRARIES = libtestcls.la

>>>>>> +libtestcls_la_SOURCES = cls.c

>>>>>> +libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)

>>>>>> +

>>>>>> +test_PROGRAMS = cls_main$(EXEEXT)

>>>>>> +dist_cls_main_SOURCES = cls_main.c

>>>>>> +

>>>>>> +cls_main_LDFLAGS = $(AM_LDFLAGS)

>>>>>> +cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)

>>>>>> +

>>>>>> +noinst_HEADERS = cls_suites.h

>>>>>> diff --git a/test/linux-generic/cls/cls.c 

>>>>>> b/test/linux-generic/cls/cls.c

>>>>>> new file mode 100644

>>>>>> index 0000000..f6df30a

>>>>>> --- /dev/null

>>>>>> +++ b/test/linux-generic/cls/cls.c

>>>>>> @@ -0,0 +1,351 @@

>>>>>> +/* Copyright (c) 2016, Linaro Limited

>>>>>> + * All rights reserved.

>>>>>> + *

>>>>>> + * SPDX-License-Identifier:     BSD-3-Clause

>>>>>> + */

>>>>>> +

>>>>>> +#include <stdlib.h>

>>>>>> +#include <string.h>

>>>>>> +#include <getopt.h>

>>>>>> +#include <unistd.h>

>>>>>> +#include <inttypes.h>

>>>>>> +

>>>>>> +#include <test_debug.h>

>>>>>> +

>>>>>> +#include <odp_api.h>

>>>>>> +#include <odp/helper/linux.h>

>>>>>> +#include <odp/helper/eth.h>

>>>>>> +#include <odp/helper/ip.h>

>>>>>> +

>>>>>> +#include <odp_packet_internal.h>

>>>>>> +

>>>>>> +#include "cls_suites.h"

>>>>>> +

>>>>>> +/** Get rid of path in filename - only for unix-type paths using 

>>>>>> '/' */

>>>>>> +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \

>>>>>> +                           strrchr((file_name), '/') + 1 : 

>>>>>> (file_name))

>>>>>> +

>>>>>> +/**

>>>>>> + * Print usage information

>>>>>> + */

>>>>>> +static void usage(char *progname)

>>>>>> +{

>>>>>> +       printf("\n"

>>>>>> +              "This is test application to verify that 

>>>>>> linux-generic

>>>>>> classifier\n"

>>>>>> +              "correctly classifies packets on input. Main 

>>>>>> intend is

>>>> add

>>>>>> more code\n"

>>>>>> +              "coverage for internal functions playing different

>>>> traffic

>>>>>> recorded to\n"

>>>>>> +              "pcap files."

>>>>>> +              "\n"

>>>>>> +              "Usage: %s OPTIONS\n"

>>>>>> +              "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"

>>>>>> +              "\n"

>>>>>> +              "Mandatory OPTIONS:\n"

>>>>>> +              "  -i, pcap file name\n"

>>>>>> +              "  -e, expected packet bitmask\n"

>>>>>> +              "\n", NO_PATH(progname), NO_PATH(progname)

>>>>>> +           );

>>>>>> +}

>>>>>> +

>>>>>> +/** @def SHM_PKT_POOL_SIZE

>>>>>> + * @brief Size of the shared memory block

>>>>>> + */

>>>>>> +#define SHM_PKT_POOL_SIZE      512

>>>>>> +

>>>>>> +/** @def SHM_PKT_POOL_BUF_SIZE

>>>>>> + * @brief Buffer size of the packet pool buffer

>>>>>> + */

>>>>>> +#define SHM_PKT_POOL_BUF_SIZE  1856

>>>>>> +

>>>>>> +/**

>>>>>> + * Parsed command line application arguments

>>>>>> + */

>>>>>> +typedef struct {

>>>>>> +       char *file_name;     /**< File name for pcap pktio */

>>>>>> +       odp_pktio_t pktio;  /**< Pktio dev */

>>>>>> +       input_flags_t expected_bits; /**< Expected bits from test 

>>>>>> run */

>>>>>> +} appl_args_t;

>>>>>> +

>>>>>> +/**

>>>>>> + * Grouping of both parsed CL args and thread specific args - alloc

>>>>>> together

>>>>>> + */

>>>>>> +typedef struct {

>>>>>> +       /** Application (parsed) arguments */

>>>>>> +       appl_args_t appl;

>>>>>> +} args_t;

>>>>>> +

>>>>>> +/** Global pointer to args */

>>>>>> +static args_t *args;

>>>>>> +/** Fill this bit struct to check which packet fields were 

>>>>>> classified

>>>> */

>>>>>> +static input_flags_t packet_flags;

>>>>>> +

>>>>>> +/**

>>>>>> + * Parse and store the command line arguments

>>>>>> + *

>>>>>> + * @param argc       argument count

>>>>>> + * @param argv[]     argument vector

>>>>>> + * @param appl_args  Store application arguments here

>>>>>> + */

>>>>>> +static void parse_args(int argc, char *argv[], appl_args_t 

>>>>>> *appl_args)

>>>>>> +{

>>>>>> +       int opt;

>>>>>> +       int long_index;

>>>>>> +       static const struct option longopts[] = {

>>>>>> +               {"interface", required_argument, NULL, 'i'},    /*

>>>> return

>>>>>> 'i' */

>>>>>> +               {"extected", required_argument, NULL, 'e'},     /*

>>>> return

>>>>>> 'e' */

>>>>>> +               {"help", no_argument, NULL, 'h'},               /*

>>>> return

>>>>>> 'h' */

>>>>>> +               {NULL, 0, NULL, 0}

>>>>>> +       };

>>>>>> +

>>>>>> +       static const char *shortopts = ":i:e:h";

>>>>>> +

>>>>>> +       /* let helper collect its own arguments (e.g. 

>>>>>> --odph_proc) */

>>>>>> +       odph_parse_options(argc, argv, shortopts, longopts);

>>>>>> +

>>>>>> +       appl_args->file_name = NULL;

>>>>>> +       opterr = 0; /* do not issue errors on helper options */

>>>>>> +       appl_args->expected_bits.all = 0;

>>>>>> +

>>>>>> +       while (1) {

>>>>>> +               opt = getopt_long(argc, argv, shortopts, longopts,

>>>>>> &long_index);

>>>>>> +

>>>>>> +               if (opt == -1)

>>>>>> +                       break;  /* No more options */

>>>>>> +

>>>>>> +               switch (opt) {

>>>>>> +               case 'i':

>>>>>> +                       appl_args->file_name = optarg;

>>>>>> +                       break;

>>>>>> +               case 'e':

>>>>>> +                       appl_args->expected_bits.all = 

>>>>>> atoll(optarg);

>>>>>> +                       break;

>>>>>> +

>>>>>> +               case 'h':

>>>>>> +                       usage(argv[0]);

>>>>>> +                       exit(EXIT_SUCCESS);

>>>>>> +                       break;

>>>>>> +               default:

>>>>>> +                       break;

>>>>>> +               }

>>>>>> +       }

>>>>>> +

>>>>>> +       if (!appl_args->file_name) {

>>>>>> +               usage(argv[0]);

>>>>>> +               exit(EXIT_SUCCESS);

>>>>>> +       }

>>>>>> +

>>>>>> +       optind = 1;             /* reset 'extern optind' from the 

>>>>>> getopt

>>>>>> lib */

>>>>>> +}

>>>>>> +

>>>>>> +/**

>>>>>> + * Create a pktio handle and configure in/out queues.

>>>>>> + *

>>>>>> + * @param fname Name of device to open

>>>>>> + * @param pool Pool to associate with device for packet RX/TX

>>>>>> + *

>>>>>> + * @return The handle of the created pktio object.

>>>>>> + * @retval ODP_PKTIO_INVALID if the create fails.

>>>>>> + */

>>>>>> +static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)

>>>>>> +{

>>>>>> +       odp_pktio_t pktio;

>>>>>> +       int ret;

>>>>>> +       odp_pktio_param_t pktio_param;

>>>>>> +       odp_pktin_queue_param_t pktin_param;

>>>>>> +       char dev[255];

>>>>>> +

>>>>>> +       odp_pktio_param_init(&pktio_param);

>>>>>> +       pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;

>>>>>> +

>>>>>> +       memset(dev, 0, 255);

>>>>>> +       sprintf(dev, "pcap:in=%s:out=test_out.pcap", fname);

>>>>>> +

>>>>>> +       /* Open a packet IO instance */

>>>>>> +       pktio = odp_pktio_open(dev, pool, &pktio_param);

>>>>>> +       if (pktio == ODP_PKTIO_INVALID)

>>>>>> +               LOG_ABORT("Error: pktio create failed for %s\n", 

>>>>>> dev);

>>>>>> +

>>>>>> +       odp_pktin_queue_param_init(&pktin_param);

>>>>>> +

>>>>>> +       pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;

>>>>>> +

>>>>>> +       if (odp_pktin_queue_config(pktio, &pktin_param))

>>>>>> +               LOG_ABORT("Error: pktin config failed for %s\n", 

>>>>>> dev);

>>>>>> +

>>>>>> +       if (odp_pktout_queue_config(pktio, NULL))

>>>>>> +               LOG_ABORT("Error: pktout config failed for %s\n", 

>>>>>> dev);

>>>>>> +

>>>>>> +       ret = odp_pktio_start(pktio);

>>>>>> +       if (ret != 0)

>>>>>> +               LOG_ABORT("Error: unable to start %s\n", dev);

>>>>>> +

>>>>>> +       printf("  created pktio:%02" PRIu64

>>>>>> +              ", dev:%s, queue mode (ATOMIC queues)\n"

>>>>>> +              "  \tdefault pktio%02" PRIu64 "\n",

>>>>>> +              odp_pktio_to_u64(pktio), dev,

>>>>>> +              odp_pktio_to_u64(pktio));

>>>>>> +

>>>>>> +       return pktio;

>>>>>> +}

>>>>>> +

>>>>>> +/**

>>>>>> + * Packet IO loopback worker thread using ODP queues

>>>>>> + *

>>>>>> + * @param arg  thread arguments of type 'thread_args_t *'

>>>>>> + *

>>>>>> + * @return 0 on success

>>>>>> + * @return !0 on any error

>>>>>> + */

>>>>>> +static int pktio_queue_thread(void *arg ODP_UNUSED)

>>>>>> +{

>>>>>> +       int thr = odp_thread_id();

>>>>>> +       odp_pktout_queue_t pktout;

>>>>>> +       odp_packet_t pkt;

>>>>>> +       odp_event_t ev;

>>>>>> +       uint64_t sched_wait = odp_schedule_wait_time(ODP_

>>>> TIME_MSEC_IN_NS

>>>>>> * 100);

>>>>>> +

>>>>>> +       packet_flags.all = 0;

>>>>>> +

>>>>>> +       /* Loop packets */

>>>>>> +       while (1) {

>>>>>> +               odp_pktio_t pktio_tmp;

>>>>>> +

>>>>>> +               ev = odp_schedule(NULL, sched_wait);

>>>>>> +               if (ev == ODP_EVENT_INVALID)

>>>>>> +                       break;

>>>>>> +

>>>>>> +               pkt = odp_packet_from_event(ev);

>>>>>> +               if (!odp_packet_is_valid(pkt))

>>>>>> +                       continue;

>>>>>> +

>>>>>> +               pktio_tmp = odp_packet_input(pkt);

>>>>>> +

>>>>>> +               if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {

>>>>>> +                       LOG_ERR("  [%02i] Error: no pktout queue\n",

>>>> thr);

>>>>>> +                       return -1;

>>>>>> +               }

>>>>>> +

>>>>>> +               /* Extend bits here for more additional tests */

>>>>>> +               if (odp_packet_has_l2(pkt))

>>>>>> +                       packet_flags.parsed_l2 = 1;

>>>>>> +               if (odp_packet_has_vlan(pkt))

>>>>>> +                       packet_flags.vlan = 1;

>>>>>> +

>>>>>> +               /* Enqueue the packet for output */

>>>>>> +               if (odp_pktout_send(pktout, &pkt, 1) != 1) {

>>>>>> +                       LOG_ERR("  [%i] Packet send failed.\n", 

>>>>>> thr);

>>>>>> +                       odp_packet_free(pkt);

>>>>>> +                       continue;

>>>>>> +               }

>>>>>> +       }

>>>>>> +

>>>>>> +       return 0;

>>>>>> +}

>>>>>> +

>>>>>> +int cls_main(int argc, char *argv[])

>>>>>> +{

>>>>>> +       odph_odpthread_t thread_tbl[1];

>>>>>> +       odp_pool_t pool;

>>>>>> +       int num_workers;

>>>>>> +       int i;

>>>>>> +       int cpu;

>>>>>> +       odp_cpumask_t cpumask;

>>>>>> +       char cpumaskstr[ODP_CPUMASK_STR_SIZE];

>>>>>> +       odp_pool_param_t params;

>>>>>> +       odp_instance_t instance;

>>>>>> +       odph_odpthread_params_t thr_params;

>>>>>> +

>>>>>> +       args = calloc(1, sizeof(args_t));

>>>>>> +       if (args == NULL) {

>>>>>> +               LOG_ERR("Error: args mem alloc failed.\n");

>>>>>> +               exit(EXIT_FAILURE);

>>>>>> +       }

>>>>>> +

>>>>>> +       parse_args(argc, argv, &args->appl);

>>>>>> +

>>>>>> +       /* Init ODP before calling anything else */

>>>>>> +       if (odp_init_global(&instance, NULL, NULL)) {

>>>>>> +               LOG_ERR("Error: ODP global init failed.\n");

>>>>>> +               exit(EXIT_FAILURE);

>>>>>> +       }

>>>>>> +

>>>>>> +       /* Init this thread */

>>>>>> +       if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

>>>>>> +               LOG_ERR("Error: ODP local init failed.\n");

>>>>>> +               exit(EXIT_FAILURE);

>>>>>> +       }

>>>>>> +

>>>>>> +       num_workers = odp_cpumask_default_worker(&cpumask, 1);

>>>>>> +       (void)odp_cpumask_to_str(&cpumask, cpumaskstr,

>>>>>> sizeof(cpumaskstr));

>>>>>> +

>>>>>> +       /* Create packet pool */

>>>>>> +       odp_pool_param_init(&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_pool", &params);

>>>>>> +       if (pool == ODP_POOL_INVALID) {

>>>>>> +               LOG_ERR("Error: packet pool create failed.\n");

>>>>>> +               exit(EXIT_FAILURE);

>>>>>> +       }

>>>>>> +

>>>>>> +       args->appl.pktio = create_pktio(args->appl.file_name, pool);

>>>>>> +

>>>>>> +       /* Create and init worker threads */

>>>>>> +       memset(thread_tbl, 0, sizeof(thread_tbl));

>>>>>> +

>>>>>> +       memset(&thr_params, 0, sizeof(thr_params));

>>>>>> +       thr_params.thr_type = ODP_THREAD_WORKER;

>>>>>> +       thr_params.instance = instance;

>>>>>> +

>>>>>> +       cpu = odp_cpumask_first(&cpumask);

>>>>>> +       for (i = 0; i < num_workers; ++i) {

>>>>>> +               odp_cpumask_t thd_mask;

>>>>>> +               int (*thr_run_func)(void *);

>>>>>> +

>>>>>> +               thr_run_func = pktio_queue_thread;

>>>>>> +               /*

>>>>>> +                * Create threads one-by-one instead of all-at-once,

>>>>>> +                * because each thread might get different 

>>>>>> arguments.

>>>>>> +                * Calls odp_thread_create(cpu) for each thread

>>>>>> +                */

>>>>>> +               odp_cpumask_zero(&thd_mask);

>>>>>> +               odp_cpumask_set(&thd_mask, cpu);

>>>>>> +

>>>>>> +               thr_params.start = thr_run_func;

>>>>>> +               thr_params.arg   = &args;

>>>>>> +

>>>>>> + odph_odpthreads_create(&thread_tbl[i], &thd_mask,

>>>>>> &thr_params);

>>>>>> +               cpu = odp_cpumask_next(&cpumask, cpu);

>>>>>> +       }

>>>>>> +

>>>>>> +       /* Master thread waits for other threads to exit */

>>>>>> +       for (i = 0; i < num_workers; ++i)

>>>>>> + odph_odpthreads_join(&thread_tbl[i]);

>>>>>> +

>>>>>> +       odp_pktio_stop(args->appl.pktio);

>>>>>> +       odp_pktio_close(args->appl.pktio);

>>>>>> +

>>>>>> +       while (1) {

>>>>>> +               odp_event_t ev;

>>>>>> +

>>>>>> +               ev = odp_schedule(NULL, 0);

>>>>>> +               if (ev == ODP_EVENT_INVALID)

>>>>>> +                       break;

>>>>>> +       }

>>>>>> +

>>>>>> +       odp_pool_destroy(pool);

>>>>>> +       odp_term_local();

>>>>>> +       odp_term_global(instance);

>>>>>> +

>>>>>> +       if (packet_flags.all != args->appl.expected_bits.all) {

>>>>>> +               LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",

>>>>>> +                       packet_flags.all, 

>>>>>> args->appl.expected_bits.all);

>>>>>> +               free(args);

>>>>>> +               return -1;

>>>>>> +       }

>>>>>> +

>>>>>> +       free(args);

>>>>>> +       return 0;

>>>>>> +}

>>>>>> diff --git a/test/linux-generic/cls/cls_main.c

>>>>>> b/test/linux-generic/cls/cls_main.c

>>>>>> new file mode 100644

>>>>>> index 0000000..40179b9

>>>>>> --- /dev/null

>>>>>> +++ b/test/linux-generic/cls/cls_main.c

>>>>>> @@ -0,0 +1,12 @@

>>>>>> +/* Copyright (c) 2016, Linaro Limited

>>>>>> + * All rights reserved.

>>>>>> + *

>>>>>> + * SPDX-License-Identifier:     BSD-3-Clause

>>>>>> + */

>>>>>> +

>>>>>> +#include "cls_suites.h"

>>>>>> +

>>>>>> +int main(int argc, char *argv[])

>>>>>> +{

>>>>>> +       return cls_main(argc, argv);

>>>>>> +}

>>>>>> diff --git a/test/linux-generic/cls/cls_suites.h

>>>>>> b/test/linux-generic/cls/cls_suites.h

>>>>>> new file mode 100644

>>>>>> index 0000000..94c9b55

>>>>>> --- /dev/null

>>>>>> +++ b/test/linux-generic/cls/cls_suites.h

>>>>>> @@ -0,0 +1 @@

>>>>>> +int cls_main(int argc, char *argv[]);

>>>>>> diff --git a/test/linux-generic/cls/vlan.pcap

>>>>>> b/test/linux-generic/cls/vlan.pcap

>>>>>> new file mode 100644

>>>>>> index 0000000000000000000000000000000000000000..106ccb682e51495b40

>>>>>> 25337518a0bce63c2c7681

>>>>>> GIT binary patch

>>>>>> literal 9728

>>>>>> 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

>>>>>> H$A|v_$relS

>>>>>>

>>>>>> literal 0

>>>>>> HcmV?d00001

>>>>>>

>>>>>> diff --git a/test/linux-generic/cls/vlan_run.sh

>>>>>> b/test/linux-generic/cls/vlan_run.sh

>>>>>> new file mode 100755

>>>>>> index 0000000..7875eaf

>>>>>> --- /dev/null

>>>>>> +++ b/test/linux-generic/cls/vlan_run.sh

>>>>>> @@ -0,0 +1,49 @@

>>>>>> +#!/bin/sh

>>>>>> +#

>>>>>> +# Copyright (c) 2016, Linaro Limited

>>>>>> +# All rights reserved.

>>>>>> +#

>>>>>> +# SPDX-License-Identifier:      BSD-3-Clause

>>>>>> +#

>>>>>> +

>>>>>> +# directories where binary can be found:

>>>>>> +# -in the validation dir when running make check (intree or out of

>>>> tree)

>>>>>> +# -in the script directory, when running after 'make install', or

>>>>>> +# -in the validation when running standalone intree,

>>>>>> +# -in the _build directory, when running after 'make distcheck',

>>>>>> +# -in the current directory.

>>>>>> +# running stand alone out of tree requires setting PATH

>>>>>> +PATH=${TEST_DIR}/linux-generic/cls:$PATH

>>>>>> +PATH=$(dirname $0):$PATH

>>>>>> +PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH

>>>>>> +PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH

>>>>>> +PATH=.:$PATH

>>>>>> +

>>>>>> +bin_path=$(which cls_main${EXEEXT})

>>>>>> +if [ -x "$bin_path" ] ; then

>>>>>> +       echo "Running with $bin_path"

>>>>>> +else

>>>>>> +       echo "Cannot find cls_main${EXEEXT}"

>>>>>> +       echo "Please set you PATH for it. PATH=$PATH"

>>>>>> +fi

>>>>>> +

>>>>>> +# Test1: find vlan packets in pcap file and test internal

>>>>>> pkt_mmap_vlan_insert()

>>>>>> +#       function. Load packets from vlan.pcap file and check that

>>>>>> classifier

>>>>>> +#       set vlan bits fisible with odp_packet_has_vlan().

>>>>>> +

>>>>>> +PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print 

>>>>>> -quit`

>>>>>> +

>>>>>> +cls_main -i $PCAP -e 4097

>>>>>> +ret=$?

>>>>>> +

>>>>>> +PCAP_IN_SIZE=`stat -c %s $PCAP`

>>>>>> +PCAP_OUT_SIZE=`stat -c %s test_out.pcap`

>>>>>> +

>>>>>> +rm -f test_out.pcap

>>>>>> +

>>>>>> +if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; 

>>>>>> then

>>>>>> +       echo "Error: status ${ret}, in:${PCAP_IN_SIZE}

>>>>>> out:${PCAP_OUT_SIZE}"

>>>>>> +       exit 3

>>>>>> +fi

>>>>>> +

>>>>>> +echo "PASS: test 1 passed"

>>>>>> diff --git a/test/linux-generic/m4/configure.m4

>>>>>> b/test/linux-generic/m4/configure.m4

>>>>>> index 6b92201..1b722f6 100644

>>>>>> --- a/test/linux-generic/m4/configure.m4

>>>>>> +++ b/test/linux-generic/m4/configure.m4

>>>>>> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

>>>>>>    AC_CONFIG_FILES([test/linux-generic/Makefile

>>>>>> test/linux-generic/validation/api/shmem/Makefile

>>>>>> test/linux-generic/validation/api/pktio/Makefile

>>>>>> +                test/linux-generic/cls/Makefile

>>>>>>                   test/linux-generic/pktio_ipc/Makefile

>>>>>>                   test/linux-generic/ring/Makefile

>>>>>> test/linux-generic/performance/Makefile])

>>>>>>

>>>>>

>>>>

>>>> -- 

>>>> Mike Holmes

>>>> Program Manager - Linaro Networking Group

>>>> Linaro.org <http://www.linaro.org/> *│ *Open source software for 

>>>> ARM SoCs

>>>> "Work should be fun and collaborative, the rest follows"

>>>>

>

Patch

diff --git a/test/linux-generic/.gitignore b/test/linux-generic/.gitignore
index 5dabf91..f65c7c1 100644
--- a/test/linux-generic/.gitignore
+++ b/test/linux-generic/.gitignore
@@ -1,3 +1,4 @@ 
 *.log
 *.trs
 tests-validation.env
+test_out.pcap
diff --git a/test/linux-generic/Makefile.am b/test/linux-generic/Makefile.am
index 4660cf0..2554f8e 100644
--- a/test/linux-generic/Makefile.am
+++ b/test/linux-generic/Makefile.am
@@ -1,5 +1,8 @@ 
 include $(top_srcdir)/test/Makefile.inc
 TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/common_plat/validation
+TEST_EXTENSIONS = .sh
+
+dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)
 
 ALL_API_VALIDATION_DIR = ${top_builddir}/test/common_plat/validation/api
 
@@ -37,11 +40,14 @@  TESTS = validation/api/pktio/pktio_run.sh \
 
 SUBDIRS += validation/api/pktio\
 	   validation/api/shmem\
+	   cls\
 	   pktio_ipc\
 	   ring
 
 if HAVE_PCAP
 TESTS += validation/api/pktio/pktio_run_pcap.sh
+TESTS += cls/vlan_run.sh
+dist_check_SCRIPTS += cls/vlan_run.sh cls/vlan.pcap
 endif
 if netmap_support
 TESTS += validation/api/pktio/pktio_run_netmap.sh
@@ -61,10 +67,6 @@  SUBDIRS += validation/api/pktio
 endif
 endif
 
-TEST_EXTENSIONS = .sh
-
-dist_check_SCRIPTS = run-test tests-validation.env $(LOG_COMPILER)
-
 test_SCRIPTS = $(dist_check_SCRIPTS)
 
 tests-validation.env:
diff --git a/test/linux-generic/cls/.gitignore b/test/linux-generic/cls/.gitignore
new file mode 100644
index 0000000..5a652b7
--- /dev/null
+++ b/test/linux-generic/cls/.gitignore
@@ -0,0 +1 @@ 
+cls_main
diff --git a/test/linux-generic/cls/Makefile.am b/test/linux-generic/cls/Makefile.am
new file mode 100644
index 0000000..43fb0bc
--- /dev/null
+++ b/test/linux-generic/cls/Makefile.am
@@ -0,0 +1,13 @@ 
+include ../Makefile.inc
+
+noinst_LTLIBRARIES = libtestcls.la
+libtestcls_la_SOURCES = cls.c
+libtestcls_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)
+
+test_PROGRAMS = cls_main$(EXEEXT)
+dist_cls_main_SOURCES = cls_main.c
+
+cls_main_LDFLAGS = $(AM_LDFLAGS)
+cls_main_LDADD = libtestcls.la $(LIBCUNIT_COMMON) $(LIBODP)
+
+noinst_HEADERS = cls_suites.h
diff --git a/test/linux-generic/cls/cls.c b/test/linux-generic/cls/cls.c
new file mode 100644
index 0000000..f6df30a
--- /dev/null
+++ b/test/linux-generic/cls/cls.c
@@ -0,0 +1,351 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <test_debug.h>
+
+#include <odp_api.h>
+#include <odp/helper/linux.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+
+#include <odp_packet_internal.h>
+
+#include "cls_suites.h"
+
+/** Get rid of path in filename - only for unix-type paths using '/' */
+#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
+			    strrchr((file_name), '/') + 1 : (file_name))
+
+/**
+ * Print usage information
+ */
+static void usage(char *progname)
+{
+	printf("\n"
+	       "This is test application to verify that linux-generic classifier\n"
+	       "correctly classifies packets on input. Main intend is add more code\n"
+	       "coverage for internal functions playing different traffic recorded to\n"
+	       "pcap files."
+	       "\n"
+	       "Usage: %s OPTIONS\n"
+	       "  E.g. %s -i pcap_file -e expected_pkt_bitmask\n"
+	       "\n"
+	       "Mandatory OPTIONS:\n"
+	       "  -i, pcap file name\n"
+	       "  -e, expected packet bitmask\n"
+	       "\n", NO_PATH(progname), NO_PATH(progname)
+	    );
+}
+
+/** @def SHM_PKT_POOL_SIZE
+ * @brief Size of the shared memory block
+ */
+#define SHM_PKT_POOL_SIZE      512
+
+/** @def SHM_PKT_POOL_BUF_SIZE
+ * @brief Buffer size of the packet pool buffer
+ */
+#define SHM_PKT_POOL_BUF_SIZE  1856
+
+/**
+ * Parsed command line application arguments
+ */
+typedef struct {
+	char *file_name;     /**< File name for pcap pktio */
+	odp_pktio_t pktio;  /**< Pktio dev */
+	input_flags_t expected_bits; /**< Expected bits from test run */
+} appl_args_t;
+
+/**
+ * Grouping of both parsed CL args and thread specific args - alloc together
+ */
+typedef struct {
+	/** Application (parsed) arguments */
+	appl_args_t appl;
+} args_t;
+
+/** Global pointer to args */
+static args_t *args;
+/** Fill this bit struct to check which packet fields were classified */
+static input_flags_t packet_flags;
+
+/**
+ * Parse and store the command line arguments
+ *
+ * @param argc       argument count
+ * @param argv[]     argument vector
+ * @param appl_args  Store application arguments here
+ */
+static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
+{
+	int opt;
+	int long_index;
+	static const struct option longopts[] = {
+		{"interface", required_argument, NULL, 'i'},	/* return 'i' */
+		{"extected", required_argument, NULL, 'e'},	/* return 'e' */
+		{"help", no_argument, NULL, 'h'},		/* return 'h' */
+		{NULL, 0, NULL, 0}
+	};
+
+	static const char *shortopts = ":i:e:h";
+
+	/* let helper collect its own arguments (e.g. --odph_proc) */
+	odph_parse_options(argc, argv, shortopts, longopts);
+
+	appl_args->file_name = NULL;
+	opterr = 0; /* do not issue errors on helper options */
+	appl_args->expected_bits.all = 0;
+
+	while (1) {
+		opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
+
+		if (opt == -1)
+			break;	/* No more options */
+
+		switch (opt) {
+		case 'i':
+			appl_args->file_name =  optarg;
+			break;
+		case 'e':
+			appl_args->expected_bits.all = atoll(optarg);
+			break;
+
+		case 'h':
+			usage(argv[0]);
+			exit(EXIT_SUCCESS);
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!appl_args->file_name) {
+		usage(argv[0]);
+		exit(EXIT_SUCCESS);
+	}
+
+	optind = 1;		/* reset 'extern optind' from the getopt lib */
+}
+
+/**
+ * Create a pktio handle and configure in/out queues.
+ *
+ * @param fname Name of device to open
+ * @param pool Pool to associate with device for packet RX/TX
+ *
+ * @return The handle of the created pktio object.
+ * @retval ODP_PKTIO_INVALID if the create fails.
+ */
+static odp_pktio_t create_pktio(const char *fname, odp_pool_t pool)
+{
+	odp_pktio_t pktio;
+	int ret;
+	odp_pktio_param_t pktio_param;
+	odp_pktin_queue_param_t pktin_param;
+	char dev[255];
+
+	odp_pktio_param_init(&pktio_param);
+	pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
+
+	memset(dev, 0, 255);
+	sprintf(dev, "pcap:in=%s:out=test_out.pcap",  fname);
+
+	/* Open a packet IO instance */
+	pktio = odp_pktio_open(dev, pool, &pktio_param);
+	if (pktio == ODP_PKTIO_INVALID)
+		LOG_ABORT("Error: pktio create failed for %s\n", dev);
+
+	odp_pktin_queue_param_init(&pktin_param);
+
+	pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;
+
+	if (odp_pktin_queue_config(pktio, &pktin_param))
+		LOG_ABORT("Error: pktin config failed for %s\n", dev);
+
+	if (odp_pktout_queue_config(pktio, NULL))
+		LOG_ABORT("Error: pktout config failed for %s\n", dev);
+
+	ret = odp_pktio_start(pktio);
+	if (ret != 0)
+		LOG_ABORT("Error: unable to start %s\n", dev);
+
+	printf("  created pktio:%02" PRIu64
+	       ", dev:%s, queue mode (ATOMIC queues)\n"
+	       "  \tdefault pktio%02" PRIu64 "\n",
+	       odp_pktio_to_u64(pktio), dev,
+	       odp_pktio_to_u64(pktio));
+
+	return pktio;
+}
+
+/**
+ * Packet IO loopback worker thread using ODP queues
+ *
+ * @param arg  thread arguments of type 'thread_args_t *'
+ *
+ * @return 0 on success
+ * @return !0 on any error
+ */
+static int pktio_queue_thread(void *arg ODP_UNUSED)
+{
+	int thr = odp_thread_id();
+	odp_pktout_queue_t pktout;
+	odp_packet_t pkt;
+	odp_event_t ev;
+	uint64_t sched_wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS * 100);
+
+	packet_flags.all = 0;
+
+	/* Loop packets */
+	while (1) {
+		odp_pktio_t pktio_tmp;
+
+		ev = odp_schedule(NULL, sched_wait);
+		if (ev == ODP_EVENT_INVALID)
+			break;
+
+		pkt = odp_packet_from_event(ev);
+		if (!odp_packet_is_valid(pkt))
+			continue;
+
+		pktio_tmp = odp_packet_input(pkt);
+
+		if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {
+			LOG_ERR("  [%02i] Error: no pktout queue\n", thr);
+			return -1;
+		}
+
+		/* Extend bits here for more additional tests */
+		if (odp_packet_has_l2(pkt))
+			packet_flags.parsed_l2 = 1;
+		if (odp_packet_has_vlan(pkt))
+			packet_flags.vlan = 1;
+
+		/* Enqueue the packet for output */
+		if (odp_pktout_send(pktout, &pkt, 1) != 1) {
+			LOG_ERR("  [%i] Packet send failed.\n", thr);
+			odp_packet_free(pkt);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+int cls_main(int argc, char *argv[])
+{
+	odph_odpthread_t thread_tbl[1];
+	odp_pool_t pool;
+	int num_workers;
+	int i;
+	int cpu;
+	odp_cpumask_t cpumask;
+	char cpumaskstr[ODP_CPUMASK_STR_SIZE];
+	odp_pool_param_t params;
+	odp_instance_t instance;
+	odph_odpthread_params_t thr_params;
+
+	args = calloc(1, sizeof(args_t));
+	if (args == NULL) {
+		LOG_ERR("Error: args mem alloc failed.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	parse_args(argc, argv, &args->appl);
+
+	/* Init ODP before calling anything else */
+	if (odp_init_global(&instance, NULL, NULL)) {
+		LOG_ERR("Error: ODP global init failed.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	/* Init this thread */
+	if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
+		LOG_ERR("Error: ODP local init failed.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	num_workers = odp_cpumask_default_worker(&cpumask, 1);
+	(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
+
+	/* Create packet pool */
+	odp_pool_param_init(&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_pool", &params);
+	if (pool == ODP_POOL_INVALID) {
+		LOG_ERR("Error: packet pool create failed.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	args->appl.pktio = create_pktio(args->appl.file_name, pool);
+
+	/* Create and init worker threads */
+	memset(thread_tbl, 0, sizeof(thread_tbl));
+
+	memset(&thr_params, 0, sizeof(thr_params));
+	thr_params.thr_type = ODP_THREAD_WORKER;
+	thr_params.instance = instance;
+
+	cpu = odp_cpumask_first(&cpumask);
+	for (i = 0; i < num_workers; ++i) {
+		odp_cpumask_t thd_mask;
+		int (*thr_run_func)(void *);
+
+		thr_run_func = pktio_queue_thread;
+		/*
+		 * Create threads one-by-one instead of all-at-once,
+		 * because each thread might get different arguments.
+		 * Calls odp_thread_create(cpu) for each thread
+		 */
+		odp_cpumask_zero(&thd_mask);
+		odp_cpumask_set(&thd_mask, cpu);
+
+		thr_params.start = thr_run_func;
+		thr_params.arg   = &args;
+
+		odph_odpthreads_create(&thread_tbl[i], &thd_mask, &thr_params);
+		cpu = odp_cpumask_next(&cpumask, cpu);
+	}
+
+	/* Master thread waits for other threads to exit */
+	for (i = 0; i < num_workers; ++i)
+		odph_odpthreads_join(&thread_tbl[i]);
+
+	odp_pktio_stop(args->appl.pktio);
+	odp_pktio_close(args->appl.pktio);
+
+	while (1) {
+		odp_event_t ev;
+
+		ev = odp_schedule(NULL, 0);
+		if (ev == ODP_EVENT_INVALID)
+			break;
+	}
+
+	odp_pool_destroy(pool);
+	odp_term_local();
+	odp_term_global(instance);
+
+	if (packet_flags.all != args->appl.expected_bits.all) {
+		LOG_ERR("Flags %" PRIu64 " expected %" PRIu64 "\n",
+			packet_flags.all, args->appl.expected_bits.all);
+		free(args);
+		return -1;
+	}
+
+	free(args);
+	return 0;
+}
diff --git a/test/linux-generic/cls/cls_main.c b/test/linux-generic/cls/cls_main.c
new file mode 100644
index 0000000..40179b9
--- /dev/null
+++ b/test/linux-generic/cls/cls_main.c
@@ -0,0 +1,12 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "cls_suites.h"
+
+int main(int argc, char *argv[])
+{
+	return cls_main(argc, argv);
+}
diff --git a/test/linux-generic/cls/cls_suites.h b/test/linux-generic/cls/cls_suites.h
new file mode 100644
index 0000000..94c9b55
--- /dev/null
+++ b/test/linux-generic/cls/cls_suites.h
@@ -0,0 +1 @@ 
+int cls_main(int argc, char *argv[]);
diff --git a/test/linux-generic/cls/vlan.pcap b/test/linux-generic/cls/vlan.pcap
new file mode 100644
index 0000000000000000000000000000000000000000..106ccb682e51495b4025337518a0bce63c2c7681
GIT binary patch
literal 9728
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
H$A|v_$relS

literal 0
HcmV?d00001

diff --git a/test/linux-generic/cls/vlan_run.sh b/test/linux-generic/cls/vlan_run.sh
new file mode 100755
index 0000000..7875eaf
--- /dev/null
+++ b/test/linux-generic/cls/vlan_run.sh
@@ -0,0 +1,49 @@ 
+#!/bin/sh
+#
+# Copyright (c) 2016, Linaro Limited
+# All rights reserved.
+#
+# SPDX-License-Identifier:      BSD-3-Clause
+#
+
+# directories where binary can be found:
+# -in the validation dir when running make check (intree or out of tree)
+# -in the script directory, when running after 'make install', or
+# -in the validation when running standalone intree,
+# -in the _build directory, when running after 'make distcheck',
+# -in the current directory.
+# running stand alone out of tree requires setting PATH
+PATH=${TEST_DIR}/linux-generic/cls:$PATH
+PATH=$(dirname $0):$PATH
+PATH=$(dirname $0)/../../../../test/linux-generic/cls:$PATH
+PATH=$(dirname $0)/../../../../_build/test/linux-generic/cls:$PATH
+PATH=.:$PATH
+
+bin_path=$(which cls_main${EXEEXT})
+if [ -x "$bin_path" ] ; then
+	echo "Running with $bin_path"
+else
+	echo "Cannot find cls_main${EXEEXT}"
+	echo "Please set you PATH for it. PATH=$PATH"
+fi
+
+# Test1: find vlan packets in pcap file and test internal pkt_mmap_vlan_insert()
+#	 function. Load packets from vlan.pcap file and check that classifier
+#	 set vlan bits fisible with odp_packet_has_vlan().
+
+PCAP=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`
+
+cls_main -i $PCAP -e 4097
+ret=$?
+
+PCAP_IN_SIZE=`stat -c %s $PCAP`
+PCAP_OUT_SIZE=`stat -c %s test_out.pcap`
+
+rm -f test_out.pcap
+
+if [ ${ret} -ne 0 ] || [ ${PCAP_IN_SIZE} -ne ${PCAP_OUT_SIZE} ]; then
+	echo "Error: status ${ret}, in:${PCAP_IN_SIZE} out:${PCAP_OUT_SIZE}"
+	exit 3
+fi
+
+echo "PASS: test 1 passed"
diff --git a/test/linux-generic/m4/configure.m4 b/test/linux-generic/m4/configure.m4
index 6b92201..1b722f6 100644
--- a/test/linux-generic/m4/configure.m4
+++ b/test/linux-generic/m4/configure.m4
@@ -3,6 +3,7 @@  m4_include([test/linux-generic/m4/performance.m4])
 AC_CONFIG_FILES([test/linux-generic/Makefile
 		 test/linux-generic/validation/api/shmem/Makefile
 		 test/linux-generic/validation/api/pktio/Makefile
+		 test/linux-generic/cls/Makefile
 		 test/linux-generic/pktio_ipc/Makefile
 		 test/linux-generic/ring/Makefile
 		 test/linux-generic/performance/Makefile])